2013-08-15 12 views
7

Po prostu bawiłem się trochę z ST w skandalu i doszedłem do punktu, w którym chciałem użyć zawartości przejezdnego typu, aby zmodyfikować mój STRef. W Haskell mógł to zrobić w następujący sposób (zaczerpnięte z wiki Haskell):Scalaz odpowiednik forM_

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

    n <- newSTRef 0 

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

    readSTRef n 

Niestety nie byłem w stanie znaleźć odpowiednik dla forM_ w scalaz. Pytanie brzmi: jak mogę to zrobić za pomocą scalaz?

Odpowiedz

6

Jak pewnie wiesz, forM_ jest odwróconą wersją mapM_.

Można użyć traverse i traverse_ (co realizowany w Scalaz), jak uogólnionych wersji mapM i mapM_.

Jako dowód zobacz, że Data.Traversable eksportuje własną implementację mapM pod względem traverse.

Wersja scalaz z sumST może wyglądać następująco:

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

Dla czytelników zastanawia się, dlaczego tak jest dużo bardziej gadatliwy niż wersja Haskell: Musimy użyć cechę Forall do reprezentowania Rank-2 Typ polimorficzny w Scala. Zobacz http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/, aby uzyskać pełniejsze wyjaśnienie.

+0

Doskonale, dziękuję bardzo! – drexin

Powiązane problemy