
I'm having some trouble using the state monad with a random number generator. I'm trying to follow the LYAH example (http://learnyouahaskell.com/for-a-few-monads-more) but apparently the state monad API has changed, so I'm using Control.Monad.Trans.State.Lazy (state monad from the transformers package). Side question: is using transformers a good idea? I've heard some people complain about mtl's performance, others don't seem to care. I'm far too new to be able to judge anything (does it even make sense to compare transformers vs. mtl?) but if one has overtaken the other I'd rather use that. Here's what I currently have: import Control.Monad.Trans.State.Lazy type GeneratorState = State StdGen genThree :: Int -> GeneratorState Int genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generator <- get let (generatedMin, state) = randomR (listMin, listMax) generator return generatedMin Although it typechecks it doesn't seem like an improvement over just using StdGen by itself. What I think I should have: genThree :: Int -> GeneratorState Int genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state randomR (listMin, listMax) return generatedMin * *I feel like I really botched this--what am I missing? * *

A good exercise will be to re-implement State, and then use it. Take a look
here: http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State.
This link will take you to a tutorial that takes you through the
implementation of State, and then uses it for random number generation.
Hope this helps. Enjoy !
On 18 April 2015 at 00:55, Thomas Jakway
I'm having some trouble using the state monad with a random number generator.
I'm trying to follow the LYAH example ( http://learnyouahaskell.com/for-a-few-monads-more) but apparently the state monad API has changed, so I'm using Control.Monad.Trans.State.Lazy (state monad from the transformers package). Side question: is using transformers a good idea? I've heard some people complain about mtl's performance, others don't seem to care. I'm far too new to be able to judge anything (does it even make sense to compare transformers vs. mtl?) but if one has overtaken the other I'd rather use that.
Here's what I currently have: import Control.Monad.Trans.State.Lazy type GeneratorState = State StdGen
genThree :: Int -> GeneratorState Int genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generator <- get let (generatedMin, state) = randomR (listMin, listMax) generator return generatedMin
Although it typechecks it doesn't seem like an improvement over just using StdGen by itself.
What I think I should have: genThree :: Int -> GeneratorState Int genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state randomR (listMin, listMax) return generatedMin
I feel like I really botched this--what am I missing?
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Regards Sumit Sahrawat

On Fri, Apr 17, 2015 at 2:25 PM, Thomas Jakway
genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state randomR (listMin, listMax) return generatedMin
What you're missing is a $: The only chagne to our genThree functions is making it "state $" instead of "state". #!/usr/bin/env runhaskell import System.Random import Control.Monad.State genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state $ randomR (listMin, listMax) return generatedMin main = do gen <- newStdGen print $ evalState (genThree 10) gen

Thank you very much! On 4/17/15 6:48 PM, Mike Meyer wrote:
On Fri, Apr 17, 2015 at 2:25 PM, Thomas Jakway
mailto:tjakway@nyu.edu> wrote: genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state randomR (listMin, listMax) return generatedMin
What you're missing is a $:
The only chagne to our genThree functions is making it "state $" instead of "state".
#!/usr/bin/env runhaskell
import System.Random import Control.Monad.State
genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state $ randomR (listMin, listMax) return generatedMin
main = do gen <- newStdGen print $ evalState (genThree 10) gen
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Ok, now the analysis. Without the $, you get this error message (ghci
7.8.3):
Couldn't match type ‘g0 -> (a0, g0)’ with ‘(a, (a0, a0))’
Expected type: (a0, a0) -> (a, (a0, a0))
Actual type: (a0, a0) -> g0 -> (a0, g0)
Relevant bindings include
genThree :: t -> a (bound at /tmp/test.hs:6:1)
Probable cause: ‘randomR’ is applied to too few arguments
In the first argument of ‘state’, namely ‘randomR’
In a stmt of a 'do' block: state randomR (listMin, listMax)
The key line is "Probable cause: 'randomR' is applied to too few
arguments". Since it takes and apparently has one argument, the most likely
cause is that the expression isn't parsed the way you expect.. So make the
parse explicit, which would be "state (randomR (listMin, listMax))". Using
the $ operator does the same thing, and reads a bit cleaner once you get
used to it.
On Fri, Apr 17, 2015 at 6:19 PM, Thomas Jakway
Thank you very much!
On 4/17/15 6:48 PM, Mike Meyer wrote:
On Fri, Apr 17, 2015 at 2:25 PM, Thomas Jakway
wrote: genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state randomR (listMin, listMax) return generatedMin
What you're missing is a $:
The only chagne to our genThree functions is making it "state $" instead of "state".
#!/usr/bin/env runhaskell
import System.Random import Control.Monad.State
genThree listMax = do --highest index in the list let listMin = 0 :: Int --lowest index in the list generatedMin <- state $ randomR (listMin, listMax) return generatedMin
main = do gen <- newStdGen print $ evalState (genThree 10) gen
_______________________________________________ Beginners mailing listBeginners@haskell.orghttp://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (3)
-
Mike Meyer
-
Sumit Sahrawat, Maths & Computing, IIT (BHU)
-
Thomas Jakway