PureScript by Example - ST and Effect? (Estimate Pi)

#1

In the latest/final version of PureScript by Example in The Eff Monad chapter there’s an exercise about estimating pi. I came up with this solution

estimatePi :: Int -> Effect Number
estimatePi total = do
  randoms <- replicateA total (random >>= \x -> random >>= \y -> pure { x, y })
  let inner = run do
    ref <- new 0.0
    foreach randoms \{x, y} -> do  
      when ((pow (x - 0.5) 2.0) + (pow (y - 0.5) 2.0) < pow 0.5 2.0)
        do
          _ <- modify ((+)1.0) ref
          pure unit
    read ref
  pure $ 4.0 * inner / (toNumber total)

First I generate random numbers then do a computation in an ST monadic context then get the result.

However, I’ve started out by something like this:

estimatePi' :: Int -> Effect Number
estimatePi' total = do
  let inside x y = (pow (x - 0.5) 2.0) + (pow (y - 0.5) 2.0) < pow 0.5 2.0
      inner = run do
        ref <- new (pure 0.0 :: Effect Number)
        for 0 total \_ -> do
          whenM (inside <$> random <*> random)
            do
              _ <- modify identity ref
              pure unit
        read ref
  pure $ 4.0 * inner / (toNumber total)

This doesn’t compile because of my use of whenM, the inner do block does not produces an Effect a (at least this is my understanding).

What I wanted to achieve is to “enter an ST monadic context” and do iterations and in every iteration create a random number and use its value to modify the value in the ST monadic context.

Is there a way to do this? Using Effect inside ST? (Hope my question makes sense.)

I’ve found this example so I thought maybe this can be done somehow, but as this is based on an earlier version of PureScript where ST was an Effect (as I understand it isn’t anymore) I’m unsure.

Thanks for your input.

#2

Your question makes perfect sense, but the answer is unfortunately “no”. You can’t use Effect inside ST because ST is for pure computations which are implemented in a stateful way; if you could execute effects during them, they wouldn’t be pure any more. This did indeed used to be possible, because ST was implemented using the old Eff monad, but that turned out to be a bit dodgy, so it was removed.

I think the approach you have in mind is probably best implemented with Effect.Ref instead.

#3

Thanks for the clarification. I had a hunch this is going to be the case … I tried so hard to get that Effect inside ST tho’ :smiley: