Fre*_*ind 1 monads refactoring functional-programming scala scalaz
我正在尝试一些代码来检查Scala中的这些幻灯片Free Monad
,并用一些稍微改变的代码创建了一个小项目.
该项目在这里:https://github.com/freewind/free-the-monads
一开始看起来一切都很好,代码干净漂亮:
def insertAndGet() = for {
_ <- Script.insert("name", "Freewind")
value <- Script.get("name")
} yield value
def insertAndDelete() = for {
_ <- Script.insert("name", "Freewind")
_ <- Script.delete("name")
value <- Script.get("name")
} yield value
def insertAndUpdateAndDelete() = for {
_ <- Script.insert("name", "Freewind1")
oriValue <- Script.update("name", "Freewind2")
_ <- Script.delete("name")
finalValue <- Script.get("name")
} yield (oriValue, finalValue)
Run Code Online (Sandbox Code Playgroud)
但是当我的逻辑很复杂时,例如有一些Script[Option[_]]
,我需要检查选项值以决定做某事,我不能再使用了for-comprehension
,代码如下:
private def isLongName(name: String): Script[Boolean] = for {
size <- Script.getLongNameConfig
} yield size.exists(name.length > _)
def upcaseLongName(key: String): Script[Option[String]] = {
Script.get(key) flatMap {
case Some(n) => for {
isLong <- isLongName(n)
} yield isLong match {
case true => Some(n.toUpperCase)
case false => Some(n)
}
case _ => Script.pure(None)
}
}
Run Code Online (Sandbox Code Playgroud)
我发现这种Free Monad
方法真的很有趣而且很酷,但我不熟悉scalaz
,只是开始学习Monad
东西,不知道如何改进它.
有没有办法让它变得更好?
PS:您可以克隆项目https://github.com/freewind/free-the-monads并亲自尝试
这是OptionT
monad变换器的一个很好的用例:
import scalaz.OptionT, scalaz.syntax.monad._
def upcaseLongName(key: String): OptionT[Script, String] = for {
n <- OptionT.optionT(Script.get(key))
isLong <- isLongName(n).liftM[OptionT]
} yield if (isLong) n.toUpperCase else n
Run Code Online (Sandbox Code Playgroud)
这里OptionT.optionT
将a转换Script[Option[String]]
为a OptionT[Script, String]
,并将.liftM[OptionT]
a Script[Boolean]
引入同一monad.
而不是这个:
println(upcaseLongName("name1").runWith(interpreter))
Run Code Online (Sandbox Code Playgroud)
你写这个:
println(upcaseLongName("name1").run.runWith(interpreter))
Run Code Online (Sandbox Code Playgroud)
您也可以直接通过调用upcaseLongName
返回,但是如果有任何机会您需要使用其他选项-y脚本组合它,那么最好让它返回.Script[Option[String]]
run
OptionT[Script, String]