我只是在玩 ST
在 scalaz 中,我想使用可遍历类型的内容来修改我的 STRef
.在 Haskell 中,我可以这样做(取自 Haskell wiki):
sumST :: Num a => [a] -> a
sumST xs = runST $ do
n <- newSTRef 0
forM_ xs $ \x -> do
modifySTRef n (+x)
readSTRef n
不幸的是,我找不到
forM_
的等效项。在 Scalaz 。所以问题是,我怎样才能用 scalaz 做到这一点?
最佳答案
您可能知道,forM_
是mapM_
的翻版.
您可以使用 traverse
和 traverse_
(在 Scalaz 中实现),作为 mapM
的通用版本和 mapM_
.
作为证明,请参见 Data.Traversable
导出自己的 mapM
实现,就traverse
而言.sumST
的 Scalaz 版本可能看起来像这样:
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)
})
对于想知道为什么它比 haskell 版本更冗长的读者:我们必须使用
Forall
在 Scala 中表示 2 级多态类型的 trait。见 http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/以获得更全面的解释。
关于Scalaz 等价于 forM_,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18255465/