Scala 斯卡拉单子??或函数组合

Scala 斯卡拉单子??或函数组合,scala,Scala,我有一个非常小的学习要求 假设我们有以下字符串 “1.1这是一项测试34” 其中 “1.1”是一章 “这是一个测试”是本章的标题 “34”是页码 总的结果应该会给我一些指示“已解析”行是否正常。 目前它只适用于“格式良好”的行(这是有意的)。 到目前为止,我有两种解决方法… 1)单子方法(虽然我不完全确定这是否正确,因此我的问题是) 我还具有以下功能,用于从“字符串”行中提取文本 def getChapter2(t: (Result, String)): Mine[(Result, String

我有一个非常小的学习要求

假设我们有以下字符串

“1.1这是一项测试34”
其中
“1.1”是一章
“这是一个测试”是本章的标题
“34”是页码

总的结果应该会给我一些指示“已解析”行是否正常。
目前它只适用于“格式良好”的行(这是有意的)。

到目前为止,我有两种解决方法…
1)单子方法(虽然我不完全确定这是否正确,因此我的问题是)

我还具有以下功能,用于从“字符串”行中提取文本

def getChapter2(t: (Result, String)): Mine[(Result, String)] = {
 val result = t._1
 val state = t._2
 result.chapter = state.substring(0, 3)
 var newState = state.substring(3)
 Attempt1((result, newState))
}

def getTitle2(t: (Result, String)): Mine[(Result, String)] = {
 val result = t._1
 val state = t._2
 result.title = state.substring(0, state.length() - 2)
 var newState = state.substring(state.length() - 2)
 Attempt1((result, newState))
}

def getPage2(t: (Result, String)): Mine[(Result, String)] = {
 val result = t._1
 val state = t._2
 result.page = state
 Attempt1((result, ""))
}
我可以考虑在代码中使用高阶函数,从Tuple2中获取值并创建Attempt1内容,但现在我想保持简单,对我来说最重要的是monad内容。

最后,这是主要的逻辑

var line = "1.1 Some awesome book 12"
val result = new Result("", "", "")    
val at1 = Attempt1((result, line))

val r = for (
  o1 <- at1;
  o2 <- getChapter2(o1);
  o3 <- getTitle2(o2);
  o4 <- getPage2(o3)
) yield (o4)

val res = r.get._1
println("chapter " + res.chapter) //1.1
println("title " + res.title) // Some awesome book
println("page " + res.page) // 12
正如你所看到的,除了返回类型(不是由一个Mine类型“包装”)之外,函数是相同的,我也有这个方法

def process(s: String, f: ((Result, String)) => (Result, String)): Result = {
 val res = new Result("", "", "")
 val t = f(res, s)
 res
}
我的主要逻辑如下

var line = "1.1 Some awesome book 12"
var fx = getChapter _ andThen getTitle _ andThen getPage
var resx = process(line, fx)
printf("title: %s%nchapter: %s%npage: %s%n", resx.title, resx.chapter, resx.page)
返回值与“Monad方法”相同

所以最后的问题是:
“单子方法”真的是单子吗??
我发现组合方法逻辑更容易,对于这种特殊情况,单子方法似乎有些过分,但请记住,这是为了学习。

我发现在这两种方法中,逻辑流都很容易推理

如果在这两种情况下都需要,可以很容易地添加或删除一个步骤来解析字符串行

我知道这段代码非常相似,有改进的余地,但现在我保持它的简单性,也许将来我会考虑一些常见的东西。


欢迎您提出建议。

首先,您的代码中不需要使用
var
s。第二,因为您使用的是字符串的
子字符串
函数,所以只需要一个部分函数,它接受子字符串的偏移量。这将是重构时的一个很好的起点,并允许在格式更改时使用不同的功能来分割行

这看起来像

def splitline(method:String)(symbol:String)(s:String) = method match {
  case "substring" => val symb = Integer.parseInt(symbol) ;(s.substring(0,symb),s.substring(symb))
}

val getTitle = splitline("substring")("3") _
就构成或一元代码而言,这取决于偏好和认知能力
您希望自己加载。

感谢您对splitline方法的建议,我认为它适合我未来的重构需求,因为我计划使用正则表达式。我同意认知加载部分。
var line = "1.1 Some awesome book 12"
var fx = getChapter _ andThen getTitle _ andThen getPage
var resx = process(line, fx)
printf("title: %s%nchapter: %s%npage: %s%n", resx.title, resx.chapter, resx.page)
def splitline(method:String)(symbol:String)(s:String) = method match {
  case "substring" => val symb = Integer.parseInt(symbol) ;(s.substring(0,symb),s.substring(symb))
}

val getTitle = splitline("substring")("3") _