2013-08-15 44 views
7

Tôi chỉ chơi xung quanh một chút với ST trong scalaz và đến điểm, nơi tôi muốn sử dụng nội dung của một kiểu di chuyển để sửa đổi STRef của tôi. Trong Haskell tôi có thể làm điều đó như sau (lấy từ wiki Haskell):Scalaz tương đương với forM_

sumST :: Num a => [a] -> a 
sumST xs = runST $ do 

    n <- newSTRef 0 

    forM_ xs $ \x -> do 
     modifySTRef n (+x) 

    readSTRef n 

Đáng tiếc là tôi đã không thể tìm ra tương đương cho forM_ trong scalaz. Vì vậy, câu hỏi là, làm thế nào tôi có thể làm điều này với scalaz?

Trả lời

6

Như bạn có thể đã biết, forM_ là phiên bản lật của mapM_.

Bạn có thể sử dụng traversetraverse_ (mà thực hiện trong Scalaz), như các phiên bản khái quát hóa của mapMmapM_.

Làm bằng chứng, thấy rằng Data.Traversable xuất việc triển khai riêng của mình mapM, theo điều khoản traverse.

Một phiên bản scalaz của sumST có thể trông như thế này:

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) 
    }) 

Đối với độc giả thắc mắc tại sao nó là như vậy nhiều hơn nữa tiết so với phiên bản Haskell: Chúng ta phải sử dụng Forall đặc điểm để đại diện cho một cấp bậc-2 kiểu đa hình ở Scala. Xem http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/ để có giải thích đầy đủ hơn.

+0

Tuyệt vời, cảm ơn bạn rất nhiều! – drexin