将一系列步骤封装在 Monad 中
Encapsulate series of steps within a Monad
试图将 Monad 理解为 "a structure that represents computations defined as sequences of steps":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 来编写新字符串的附加。我仍然没有完全理解 monad,但感觉更接近了。
我发现以理解形式编写 monad 的特定类比更容易理解,
for {
cbr <- convertBr(parseService.getHtml("")) //step 1
cs <- convertStyle(cbr) //step 2
} yield cs
直接编译成您在段中编写的 flatmap
形式。在这种情况下,每一行都是一个 step 并且 Option
monad 提供了 how 步骤链接在一起并解释的逻辑.
在这种情况下,Option
monad 在前一步没有 return 存在的值时终止后续步骤,即 None
但允许计算继续时值是 returned 即 Some
.
def flatMap[B](f: A => Option[B]): A = this match {
case Some(a) => f(a)
case None => None
}
然后可以将 monad 视为 计算上下文,其中发生的步骤与 flatmap
确定计算如何进行。
但值得注意的是 这只是一个 analogy/metaphor。 monad 只是遵循 monadic laws.
的东西
最重要的法则可以简单地用scala写出来,
val ab = for {
a <- genA
b <- genB
} yield (a, b)
val ba = for {
b <- genB
a <- genA
} yield (a, b)
assert(ab == ba)
试图将 Monad 理解为 "a structure that represents computations defined as sequences of steps":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 来编写新字符串的附加。我仍然没有完全理解 monad,但感觉更接近了。
我发现以理解形式编写 monad 的特定类比更容易理解,
for {
cbr <- convertBr(parseService.getHtml("")) //step 1
cs <- convertStyle(cbr) //step 2
} yield cs
直接编译成您在段中编写的 flatmap
形式。在这种情况下,每一行都是一个 step 并且 Option
monad 提供了 how 步骤链接在一起并解释的逻辑.
在这种情况下,Option
monad 在前一步没有 return 存在的值时终止后续步骤,即 None
但允许计算继续时值是 returned 即 Some
.
def flatMap[B](f: A => Option[B]): A = this match {
case Some(a) => f(a)
case None => None
}
然后可以将 monad 视为 计算上下文,其中发生的步骤与 flatmap
确定计算如何进行。
但值得注意的是 这只是一个 analogy/metaphor。 monad 只是遵循 monadic laws.
的东西最重要的法则可以简单地用scala写出来,
val ab = for {
a <- genA
b <- genB
} yield (a, b)
val ba = for {
b <- genB
a <- genA
} yield (a, b)
assert(ab == ba)