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.