nie*_*aki 7 monads scala monad-transformers scalaz scalaz7
我计划在我的Scala代码中开始使用Monadic样式,其中包括线程状态.这是一个结合3个monadic函数的简化示例(并且仅关注副作用)
import scalaz._
import Scalaz._
object MonadTest {
def adder(i: Int) = State[String, Int] ({str: String => (str + i.toString + " ", i) })
val oneTwoThreeMonad = for {
m1 <- adder(1)
m2 <- adder(2)
m3 <- adder(3)
} yield m3
oneTwoThreeMonad("start: ")._1 //String = "start: 1 2 3 "
}
Run Code Online (Sandbox Code Playgroud)
这一切都是不言自明的,并按预期工作.但是对于这种对我来说非常有用的方法,我希望能够将它与Listfor-comprehension 结合起来.这是一些(不工作)代码来显示我的意思:
val list = List(1, 2, 3)
val oneTwoThreeBis = for {
i <- list
mx <- adder(i)
} yield mx
Run Code Online (Sandbox Code Playgroud)
基本上我希望能够基于来自a的参数组合monad List- 运行monadic函数对其中的每个元素list并且在我去的时候积累副作用.我理解示例语法不起作用,我明白为什么它没有 - 我只是在寻找一个干净,优雅的等价物.
我很确定使用scalaz monad变换器可以实现这一点,更具体地来说,StateT但是我不确定如何使用它.
PS.我使用的是Scalaz 7.0-M3,因此语法可能与最常见的6.x略有不同.
我不确定我到底知道你在寻找什么,但听起来你想要更像traverse这里的东西(traverseHaskell的更通用的版本mapM):
import scalaz._, Scalaz._
def adder(i: Int) = State[String, Int](str => (str + i.toString + " ", i))
List(1, 2, 3).traverseS(adder)("start: ")._1
Run Code Online (Sandbox Code Playgroud)
这将按预期打印以下内容:
res0: String = "start: 1 2 3 "
Run Code Online (Sandbox Code Playgroud)
请注意,我正在使用traverseS(S代表的地方State)以避免写出相当混乱的类型参数,但是traverse当你想要将monadic函数映射到可遍历的东西时,它通常更有用.
StateT如果这不是你想要的,我很乐意举个例子,但这最终会让你有类型的东西List[(String, Int)].