Random Numbers with the State Monad

I'm having a bad time using the State monad to generate random numbers without carrying around a lot of StdGens manually. I have this snippet in the IO monad: ... IO stuff ... gen <- getStdGen let (numPlayers, numMatches) = (evalState genRandVariables gen) :: (Integer, Integer) ... More IO stuff ... where maxRandPlayers = 10 :: Integer minRandMatches = 10 :: Integer maxRandMatches = 100 :: Integer genRandVariables = (do np <- randomR (1, maxRandPlayers) --minimum 1 other player nm <- randomR (minRandMatches, maxRandMatches) return (np, nm)) :: State StdGen (Integer, Integer) I get this error message: test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:53:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g0 -> (Integer, g0)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: np <- randomR (1, maxRandPlayers) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer) test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:54:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g1 -> (Integer, g1)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: nm <- randomR (minRandMatches, maxRandMatches) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer) What's really baffling to me is I feel like this is how it *should* look--that the whole point of the state monad is to *not* have to explicitly pass the StdGen to randomR. What am I doing wrong?

Hi!
Take a look at MonadRandom [1]. It is basically what you want without getting generator explicitly.
[1] https://hackage.haskell.org/package/MonadRandom
With regards,
Nikita Kartashov
On 12 Feb 2016, at 04:14, Thomas Jakway
I'm having a bad time using the State monad to generate random numbers without carrying around a lot of StdGens manually. I have this snippet in the IO monad:
... IO stuff ... gen <- getStdGen let (numPlayers, numMatches) = (evalState genRandVariables gen) :: (Integer, Integer) ... More IO stuff ...
where maxRandPlayers = 10 :: Integer minRandMatches = 10 :: Integer maxRandMatches = 100 :: Integer genRandVariables = (do np <- randomR (1, maxRandPlayers) --minimum 1 other player nm <- randomR (minRandMatches, maxRandMatches) return (np, nm)) :: State StdGen (Integer, Integer)
I get this error message: test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:53:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g0 -> (Integer, g0)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: np <- randomR (1, maxRandPlayers) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer)
test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:54:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g1 -> (Integer, g1)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: nm <- randomR (minRandMatches, maxRandMatches) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer)
What's really baffling to me is I feel like this is how it *should* look--that the whole point of the state monad is to *not* have to explicitly pass the StdGen to randomR. What am I doing wrong? _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

That's a good idea, though not understanding the state monad is still pretty frustrating. On 2/12/16 6:38 AM, Nikita Kartashov wrote:
Hi!
Take a look at MonadRandom [1]. It is basically what you want without getting generator explicitly.
[1] https://hackage.haskell.org/package/MonadRandom
With regards, Nikita Kartashov
On 12 Feb 2016, at 04:14, Thomas Jakway
mailto:tjakway@nyu.edu> wrote: I'm having a bad time using the State monad to generate random numbers without carrying around a lot of StdGens manually. I have this snippet in the IO monad:
... IO stuff ... gen <- getStdGen let (numPlayers, numMatches) = (evalState genRandVariables gen) :: (Integer, Integer) ... More IO stuff ...
where maxRandPlayers = 10 :: Integer minRandMatches = 10 :: Integer maxRandMatches = 100 :: Integer genRandVariables = (do np <- randomR (1, maxRandPlayers) --minimum 1 other player nm <- randomR (minRandMatches, maxRandMatches) return (np, nm)) :: State StdGen (Integer, Integer)
I get this error message: test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:53:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g0 -> (Integer, g0)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: np <- randomR (1, maxRandPlayers) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer)
test/Jakway/Blackjack/Tests/IntegrationTests/MatchTests.hs:54:23: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g1 -> (Integer, g1)’ Probable cause: ‘randomR’ is applied to too few arguments In a stmt of a 'do' block: nm <- randomR (minRandMatches, maxRandMatches) In the expression: (do { np <- randomR (1, maxRandPlayers); nm <- randomR (minRandMatches, maxRandMatches); return (np, nm) }) :: State StdGen (Integer, Integer)
What's really baffling to me is I feel like this is how it *should* look--that the whole point of the state monad is to *not* have to explicitly pass the StdGen to randomR. What am I doing wrong? _______________________________________________ Beginners mailing list Beginners@haskell.org mailto:Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hello, You have this type error: Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g1 -> (Integer, g1)’ It's because you're trying to use a `(s -> (a,s))` function "unwrapped" where GHC expects it "wrapped" in a StateT. The type of `state` from Control.Monad.State (mtl package) is: state :: (s -> (a, s)) -> m a so it could solve your mismatch, turning `g1 -> (Integer, g1)` into `StateT StdGen Identity Integer`, like: np <- state (randomR (1, maxRandPlayers)) Alternatively, if you don't want to use mtl, you can use `StateT`s constructor directly. It's type is: StateT :: (s -> m (a, s)) -> StateT s m a so you'd have to compose `randomR` with `return` (or `pure`) first: np <- StateT (return . randomR (1, maxRandPlayers)) Best regards, Marcin Mrotek

Thanks! That makes sense On 2/12/16 8:26 AM, Marcin Mrotek wrote:
Hello,
You have this type error:
Couldn't match expected type ‘StateT StdGen Data.Functor.Identity.Identity Integer’ with actual type ‘g1 -> (Integer, g1)’
It's because you're trying to use a `(s -> (a,s))` function "unwrapped" where GHC expects it "wrapped" in a StateT. The type of `state` from Control.Monad.State (mtl package) is:
state :: (s -> (a, s)) -> m a
so it could solve your mismatch, turning `g1 -> (Integer, g1)` into `StateT StdGen Identity Integer`, like:
np <- state (randomR (1, maxRandPlayers))
Alternatively, if you don't want to use mtl, you can use `StateT`s constructor directly. It's type is:
StateT :: (s -> m (a, s)) -> StateT s m a
so you'd have to compose `randomR` with `return` (or `pure`) first:
np <- StateT (return . randomR (1, maxRandPlayers))
Best regards, Marcin Mrotek _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (3)
-
Marcin Mrotek
-
Nikita Kartashov
-
Thomas Jakway