试图将Monads理解为“表示定义为步骤序列的计算的结构”:https://en.wikipedia.org/wiki/Monad_(functional_programming)
这个例子:
def optionAdd(x:Option[Int], y:Option[Int]):Option[Int] =
for(xx <- x; yy <- y) yield xx+yy
取自Scala Monad - Full worked example。这个monad以预定义的顺序连接两个字符串。
我正在尝试将这些步骤包含在monad中:
1. Get String to be converted to html
2. Perform series of replace statements on the String to create html compliant String
def getString = {
"def test() \n { }"
} //> getString: => String
val stringOption = Option(getString); //> stringOption : Option[String] = Some(def test()
//| { })
def createHtmlMonad(x: Option[String]): Option[String] =
Option(x.get.replace("\n", "<br>").replace("def", "<div style=\"color:red\" </div>"));
//> createHtmlMonad: (x: Option[String])Option[String]
val h = createHtmlMonad(stringOption); //> h : Option[String] = Some(<div style="color:red" </div> test() <br> { })
createHtmlMonad方法不是Monad吗?这个功能可以封装在Monad中吗?
我可以创建一个封装一系列步骤的新方法,但这不是Monad:
def getString = {
"def test() \n { }"
} //> getString: => String
def stepsToCreateHtml(stringOption: Option[String]) = {
val replaceBr = Option(stringOption.get.replace("\n", "<br>"))
val replaceStyle = Option(replaceBr.get.replace("def", "<div style=\"color:red\" </div>"))
replaceStyle
} //> stepsToCreateHtml: (stringOption: Option[String])Option[String]
val stringOption = Option(getString); //> stringOption : Option[String] = Some(def test()
//| { })
val html = stepsToCreateHtml(stringOption); //> html : Option[String] = Some(<div style="color:red" </div> test() <br> { })
//|
更新: 我认为这有助于回答这个问题。我没有创建一个新的monad,而是重用现有的Option monad:
object t extends App {
println(parseService.getHtml("").flatMap(convertBr).flatMap(convertStyle))
def convertBr = (str: String) => Option(str.replaceAll("\n", "<br>"))
def convertStyle = (str: String) => Option(str.replaceAll("def", "<div style= color : \"red\"></div>"))
}
object parseService {
def getHtml(str: String): Some[String] = {
Some("test \n newline def")
}
}
这基于https://medium.com/@sinisalouc/demystifying-the-monad-in-scala-cc716bb6f534#.xprt8msoc。 monad本身只是一个包装器,其价值在于如何与要实现的功能组合,在这种情况下,我使用Option monad来编译新Strings的附加。我仍然不完全了解monad,但感觉更接近。
答案 0 :(得分:1)
我发现,当monad用于理解形式时,它更容易理解monad的特殊类比,
for {
cbr <- convertBr(parseService.getHtml("")) //step 1
cs <- convertStyle(cbr) //step 2
} yield cs
直接汇编到您在细分中写入的flatmap
表单。在这种情况下,每一行都是步骤,Option
monad提供如何步骤链接在一起并解释的逻辑。
在这种情况下,当前一步未返回存在的值时,Option
monad终止后续步骤,即None
,但允许计算在返回值时继续,即a Some
。
def flatMap[B](f: A => Option[B]): A = this match {
case Some(a) => f(a)
case None => None
}
然后monad可以被认为是计算上下文,其中步骤发生在flatmap
确定计算如何进行。
值得注意的是,这只是一个类比/隐喻。 monad简单地遵循 monadic law 。
最重要的法律可以简单地用scala编写,
val ab = for {
a <- genA
b <- genB
} yield (a, b)
val ba = for {
b <- genB
a <- genA
} yield (a, b)
assert(ab == ba)