Scalaz 为有状态计算提供了一个很好的抽象:ST monad。

ST monad 允许以函数形式捕获副作用计算。

我想,在 Haskell 中,使用这样的 monad 是有效实现某些命令式算法的唯一方法。

但在 Scala 中,如有必要,我可以简单地使用可变数据结构。

我发现,使用 Scalaz 的函数概念会带来计算开销。参见例如 this question .因此,如果期望的目标是提高效率,那么使用 ST monad 从功能实现切换到功能实现似乎是不合理的。

我要问的是:

  • 什么时候使用 ST monad 是合理的?
  • 您在哪些情况下使用它并且它似乎是一个不错的选择?
  • 请您参考如下方法:

    正如 Don Stewart 正确指出的那样,您似乎在寻找 ST monad 而不是 state monad。所以我的回答将是关于这个的。

    ST monad 用于在 Haskell 中允许本地可变性,通常不允许可变性。例如,如果你想写一个命令式 sum函数,你会使用 ST monad。带有 scalaz 的此类函数的示例是(取自 here ):

    def sumST[S, A](as: List[A])(implicit A: Numeric[A]): ST[S, A] = 
      for { n <- newVar(A.zero) 
            _ <- as.traverseU(a => n.mod(A.plus(_, a))) 
            m <- n.read } yield m 
     
    def sum[A : Numeric](as: List[A]): A = 
      runST(new Forall[({type λ[S] = ST[S, A]})#λ] { 
        def apply[S] = sumST[S, A](as) 
      }) 
    

    显然在 Scala 中我们也可以这样写:
    def sum[A](xs: List[A])(implicit N: Numeric[A]) = { 
      var sum = N.zero 
      val it = xs.iterator 
      while (it.hasNext) { 
        sum = N.plus(sum, it.next) 
      } 
      sum 
    } 
    

    这仍然是引用透明的,因为没有可变状态超出函数的范围。在 Haskell 中,它用于这些情况,因为我们根本不能有 var .

    那么我们为什么要在scala中使用ST呢?如果您想处理可变结构(如数组)并想保证该可变结构不会超出计算范围,而是必须先变成不可变结构,则可以使用 ST。在 scalaz 你有 STArray 对于这种情况,这将变成 ImmutableArray当 ST monad 正在运行时。一个很好的例子是 binary sort example in scalaz .值得一读的还有 blog article on ST monad来自 Rúnar Bjarnason。


    评论关闭
    IT干货网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!