7

I was just playing around a bit with ST in scalaz and came to the point, where I wanted to use the contents of a traversable type to modify my STRef. In Haskell I could do that as follows (taken from the Haskell wiki):

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

   n <- newSTRef 0

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

   readSTRef n

Unfortunately I have not been able to find the equivalent for forM_ in scalaz. So the question is, how can I do this with scalaz?

drexin
  • 24,225
  • 4
  • 67
  • 81

1 Answers1

6

As you probably know, forM_ is a flipped version of mapM_.

You can use traverse and traverse_ (which are implemented in Scalaz), as generalised versions of mapM and mapM_.

As proof, see that Data.Traversable exports its own implementation of mapM, in terms of traverse.

A scalaz version of sumST might look like this:

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

For readers wondering why it is so much more verbose than the haskell version: We must use the Forall trait to represent a rank-2 polymorphic type in Scala. See http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/ for a fuller explanation.

Ben James
  • 121,135
  • 26
  • 193
  • 155