我只是在scalaz中使用ST
玩了一下,然后我想使用可遍历类型的内容修改我的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
很遗憾,我无法在scalaz中找到forM_
的等效内容。所以问题是,我怎样才能用scalaz做到这一点?
答案 0 :(得分:6)
您可能知道,forM_
是mapM_
的翻转版本。
您可以使用traverse
和traverse_
( 在Scalaz中实现),作为mapM
和mapM_
的通用版本。
作为证据,请参阅Data.Traversable
以mapM
为出口traverse
导出其自己的sumST
实施。
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)
})
的scalaz版本可能如下所示:
Forall
读者想知道为什么它比haskell版本更冗长:我们必须使用{{1}}特征来表示Scala中的rank-2多态类型。有关更全面的解释,请参阅http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/。