I need to read some amount of bits from Get monad. Now my code looks like
readBits :: Int -> Int -> Get (Word32, Int)
readBits count state = ...
readValue :: Get (Word32, Word32)
readValue = do
-- read fst bit count
(bits1, s0) <- readBits 5 0
-- read bits1 bits as fst
(fst, s1) <- readBits bits1 s0
-- read snd bit count
(bits2, s2) <- readBits 5 s1
-- read bits2 bits as snd
(snd, s3) <- readBits bits2 s2
-- flush incomplete byte
when (s3 /= 0) $ skip 1
return (fst, snd)
I want to wrap this into some kind of state monad, to have code like
readBits :: Int -> BitReader Word32
readBits count = ...
runBitReader :: BitReader a -> Get a
readValue :: Get (Word32, Word32)
readValue = runBitReader $ do
bits1 <- readBits 5
fst <- readBits bits1
bits2 <- readBits 5
snd <- readBits bits2
return (fst, snd)
What functions should I implement? How should they be implemented?
I have looked into Get and BitGet source code, but not fully understand what's going on.
This is the most typical usecase for Monad Transformers.
You have defined most of the structure correctly. To answer your questions
What functions should I implement?
Well you first need to wrap Get monad into the StateT Transformer to get BitReader.
You need to implement proper definition for readBits using get to get the current state and put to save the state back.
You need to run your code wrapped in BitReader to get back the output in Get Monad. So you need to define runBitReader using runStateT.
To answer your next question.
How should they be implemented?
I have given the possible implementation. You still need to define some functions to make it work.
import Control.Monad.State
import qualified Control.Monad.State as ST
import Data.Binary
type BitReader = StateT Int Get
readBits' :: Int -> Int -> Get (Word32, Int)
readBits' = undefined
readBits :: Int -> BitReader Word32
readBits n = do
s0 <- ST.get
(a,s1) <- lift $ readBits' n s0
ST.put s1
return a
runBitReader :: BitReader a -> Get a
runBitReader w = do
(a,s) <- runStateT w 0
return a
readValue = do
fst <- readBits 5
snd <- readBits 10
return (fst, snd)
I don't know how looking into code of Get was going to help you. You were looking in the wrong house. You need to read about State Monads and Monad Transformers.
You can read more about monad transformers here.
Related
I am trying to get a good grasp of the State-Monad (and Monads in general) but I am struggling with rewriting the below function using the state Monad and the do-notation, which resulted as an exercise for me propose here
import Control.Monad
import System.Random
import Data.Complex
import qualified System.Random as R
import Control.Monad.Trans.State.Lazy
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
let n = length lst
rand <- state $ randomR (0, n-1)
return $ lst !! rand
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- state $ randomR (0, 1) :: StateT StdGen Data.Functor.Identity.Identity a
if (tal == 0) then true_answer
else giveRandomElement answers
As is immediately obvious there are some type problems for the tal-variable as it occurs in the if-clause and the first line of the do-expression. As is visible from the code I have tried to force the latter by a specific type in order to make it unambiguous and clearer for myself as well. I have done so by the compiler-suggestion I got when I first tried to force it to be of the Int-type. I Am however not able to use that value in an if-statement, and I am unsure of how to convert or unpack the value such that I get it as an Int.
So far I have tried to add the folloowing line after tal <- ... , resp <- get $ tal but I get this output.
error:
* Couldn't match expected type: t0
-> StateT StdGen Data.Functor.Identity.Identity a1
with actual type: StateT s0 m0 s0
* The first argument of ($) takes one value argument,
but its type `StateT s0 m0 s0' has none
In a stmt of a 'do' block: resp <- get $ tal
In the expression:
do tal <- state $ randomR (0, 1)
resp <- get $ tal
if (resp == 0) then
giveRandomElement answers
else
giveRandomElement answers
* Relevant bindings include tal :: t0
Furthermore I am baffled what would be the best way to 'print' the result returned by giveRandomElement as the type is based on the type declared for the State-monad which as I understand it doesn't use the deriving Show also. But this can perhaps be solved by unpacking the value as enquired about above.
EDIT
I used the above packages although they are probably not all used in the above code. I am unsure of which is used by the code by I suspect the qualified System.Random as R
The following code line:
tal <- state $ randomR (0, 1) :: StateT StdGen Data.Functor.Identity.Identity a
is quite long and might cause a horizontal slider to appear, at least on my platform.
So it is all too easy to overlook that at its very end, the a type variable is used, while it should be just Int.
Also, the two branches of the if construct use different types, making the construct ill-typed. The then branch gives a pure a value, while the else branch gives a monadic value. This is easily fixed by changing to:
if (tal == 0) then return true_answer
as the (slightly misnamed) return library function wraps its argument into the monad at hand.
The following code, which tries to keep code lines short enough, seems to work fine:
import Control.Monad.State
import qualified System.Random as R
import qualified Data.Functor.Identity as DFI
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
let n = length lst
rand <- state $ R.randomR (0, n-1)
return $ lst !! rand
type ActionType = StateT R.StdGen DFI.Identity Int
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- (state $ R.randomR (0, 1) :: ActionType)
if (tal == 0) then return true_answer
else giveRandomElement answers
main :: IO ()
main = do
let g0 = R.mkStdGen 4243
action = random_response_monad 20 [0..9]
(k, g1) = runState action g0
putStrLn $ "k is set to: " ++ (show k)
Side note: the code can also be made to compile without the complex type annotation, like this:
tal <- state $ R.randomR (0::Int, 1)
Something like this seems to work:
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
tal <- state $ randomR (0 :: Int, 1)
if (tal == 0) then return true_answer
else giveRandomElement answers
Two changes:
Use a type annotation to tell the compiler what you mean by 0 and 1. Once you've told the compiler which type 0 is, it follows that 1 has the same type. (Keep in mind that in Haskell, numbers are polymorphic. Without more information, Haskell will see a literal such as 0 as potentially any Num instance.)
return in front of true_answer.
Here's a few samples from GHCi that seems to indicate that it works:
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
4
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
1
ghci> evalState (random_response_monad 42 [0..9]) <$> newStdGen
42
I'm writing some code (around card-playing strategies) that uses State and recursion together. Perhaps this part doesn't need to actually (it already feels clumsy to me, even as a relative beginner), but there are other parts that probably do so my general question stands...
My initial naive implementation is entirely deterministic (the choice of bid is simply the first option provided by the function validBids):
bidOnRound :: (DealerRules d) => d -> NumCards -> State ([Player], PlayerBids) ()
bidOnRound dealerRules cardsThisRound = do
(players, bidsSoFar) <- get
unless (List.null players) $ do
let options = validBids dealerRules cardsThisRound bidsSoFar
let newBid = List.head $ Set.toList options
let p : ps = players
put (ps, bidsSoFar ++ [(p, newBid)])
bidOnRound dealerRules cardsThisRound
And I call it from:
playGame :: (DealerRules d, ScorerRules s) => d -> s -> StateT Results IO ()
...
let (_, bidResults) = execState (bidOnRound dealerRules cardsThisRound) (NonEmpty.toList players, [])
Now I'm aware that I need to bring randomness into this and several other parts of the code. Not wanting to litter IO everywhere, nor pass round random seeds manually all the time, I feel I should be using MonadRandom or something. A library I'm using uses it to good effect. Is this a wise choice?
Here's what I tried:
bidOnRound :: (DealerRules d, RandomGen g) => d -> NumCards -> RandT g (State ([Player], PlayerBids)) ()
bidOnRound dealerRules cardsThisRound = do
(players, bidsSoFar) <- get
unless (List.null players) $ do
let options = Set.toList $ validBids dealerRules cardsThisRound bidsSoFar
rnd <- getRandomR (0 :: Int, len options - 1)
let newBid = options List.!! rnd
let p : ps = players
put (ps, bidsSoFar ++ [(p, newBid)])
bidOnRound dealerRules cardsThisRound
but I'm uncomfortable already, plus can't work out how to call this, e.g. using evalRand in combination with execState etc. The more I read on MonadRandom, RandGen and mtl vs others, the less sure I am of what I'm doing...
How should I neatly combine Randomness and State and how do I call these properly?
Thanks!
EDIT: for reference, full current source on Github.
Well how about an example to help you out. Since you didn't post a full working code snippet I'll just replace a lot of your operations and show how the monads can be evaluated:
import Control.Monad.Trans.State
import Control.Monad.Random
import System.Random.TF
bidOnRound :: (RandomGen g) => Int -> RandT g (State ([Int], Int)) ()
bidOnRound i =
do rand <- getRandomR (10,20)
s <- lift $ get
lift $ put ([], i + rand + snd s)
main :: IO ()
main =
do g <- newTFGen
print $ flip execState ([],1000) $ evalRandT (bidOnRound 100) g
The thing to note here is you "unwrap" the outer monad first. So if you have RandT (StateT Reader ...) ... then you run RandT (ex via evalRandT or similar) then the state then the reader. Secondly, you must lift from the outer monad to use operations on the inner monad. This might seem clumsy and that is because it is horribly clumsy.
The best developers I know - those whose code I enjoy looking at and working with - extract monad operations and provide an API with all the primitives complete so I don't need to think about the structure of the monad while I'm thinking about the structure of the logic I'm writing.
In this case (it will be slightly contrived since I wrote the above without any application domain, rhyme or reason) you could write:
type MyMonad a = RandT TFGen (State ([Int],Int)) a
runMyMonad :: MyMonad () -> IO Int
runMyMonad f =
do g <- newTFGen
pure $ snd $ flip execState ([],1000) $ evalRandT f g
With the Monad defined as a simple alias and execution operation the basic functions are easier:
flipCoin :: MyMonad Int
flipCoin = getRandomR (10,20)
getBaseValue :: MyMonad Int
getBaseValue = snd <$> lift get
setBaseValue :: Int -> MyMonad ()
setBaseValue v = lift $ state $ \s -> ((),(fst s, v))
With that leg-work out of the way, which is usually a minor part of making a real application, the domain specific logic is easier to write and certainly easier to read:
bidOnRound2 :: Int -> MyMonad ()
bidOnRound2 i =
do rand <- flipCoin
old <- getBaseValue
setBaseValue (i + rand + old)
main2 :: IO ()
main2 = print =<< runMyMonad (bidOnRound2 100)
I'm writing a program that should be able to simulate many instances of trying the martingale betting system with roulette. I would like main to take an argument giving the number of tests to perform, perform the test that many times, and then print the number of wins divided by the total number of tests. My problem is that instead of ending up with a list of Bool that I could filter over to count successes, I have a list of IO Bool and I don't understand how I can filter over that.
Here's the source code:
-- file: Martingale.hs
-- a program to simulate the martingale doubling system
import System.Random (randomR, newStdGen, StdGen)
import System.Environment (getArgs)
red = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]
martingale :: IO StdGen -> IO Bool
martingale ioGen = do
gen <- ioGen
return $ martingale' 1 0 gen
martingale' :: Real a => a -> a -> StdGen -> Bool
martingale' bet acc gen
| acc >= 5 = True
| acc <= -100 = False
| otherwise = do
let (randNumber, newGen) = randomR (0,37) gen :: (Int, StdGen)
if randNumber `elem` red
then martingale' 1 (acc + bet) newGen
else martingale' (bet * 2) (acc - bet) newGen
main :: IO ()
main = do
args <- getArgs
let iters = read $ head args
gens = replicate iters newStdGen
results = map martingale gens
--results = map (<-) results
print "THIS IS A STUB"
Like I have in my comments, I basically want to map (<-) over my list of IO Bool, but as I understand it, (<-) isn't actually a function but a keyword. Any help would be greatly appreciated.
map martingale gens will give you something of type [IO Bool]. You can then use sequence to unpack it:
sequence :: Monad m => [m a] -> m [a]
A more natural alternative is to use mapM directly:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
i.e. you can write
results <- mapM martingale gens
Note - even after doing it this way, your code feels a bit unnatural. I can see some advantages to the structure, in particular because martingale' is a pure function. However having something of type IO StdGen -> IO Bool seems a bit odd.
I can see a couple of ways to improve it:
make martingale' return an IO type itself and push the newStdGen call all the way down into it
make gens use replicateM rather than replicate
You may want to head over to http://codereview.stackexchange.com for more comprehensive feedback.
In the following code, how can I replace put 1 with some code that insert nondeterministically 1 or 2 in the state?
import Control.Monad.List
import Control.Monad.Trans.State
test :: StateT Int [] Int
test = do
put 1
v <- get
return v
Your monad stack signature is already the correct one.
Lift a computation from the [] monad and bind to its value. This will fork the computation:
test :: StateT Int [] Int
test = do
s <- lift [1,2,3]
put s
v <- get
return v
Testing to see it works:
*Main> runStateT test 10
[(1,1),(2,2),(3,3)]
Not only there are many results, but the state gets included in the nondeterminism as well.
If test had had type ListT (State Int) Int, only the results would have been nondetermistic, the state would have been shared among all the branches in the computation:
test :: ListT (State Int) Int
test = do
s <- ListT $ return [1,2,3]
put s
v <- get
return v
The result:
*Main> runState (runListT test) 10
([1,2,3],3)
maybe you want something like this instead:
import Control.Monad.List
import Control.Monad.Trans.State
import System.Random (randomIO)
test :: StateT Int IO Int
test = do
put1 <- liftIO $ randomIO
put (if put1 then 1 else 2)
v <- get
return v
This will use the global generator to set 1 or 2 at random
This question already has answers here:
Random number in Haskell [duplicate]
(5 answers)
Closed 8 years ago.
I am in the process of learning Haskell and to learn I want to generate a random Int type. I am confused because the following code works. Basically, I want an Int not an IO Int.
In ghci this works:
Prelude> import System.Random
Prelude System.Random> foo <- getStdRandom (randomR (1,1000000))
Prelude System.Random> fromIntegral foo :: Int
734077
Prelude System.Random> let bar = fromIntegral foo :: Int
Prelude System.Random> bar
734077
Prelude System.Random> :t bar
bar :: Int
So when I try to wrap this up with do it fails and I don't understand why.
randomInt = do
tmp <- getStdRandom (randomR (1,1000000))
fromIntegral tmp :: Int
The compiler produces the following:
Couldn't match expected type `IO b0' with actual type `Int'
In a stmt of a 'do' block: fromIntegral tmp :: Int
In the expression:
do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
In an equation for `randomInt':
randomInt
= do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
Failed, modules loaded: none.
I am new to Haskell, so if there is a better way to generate a random Int without do that would be preferred.
So my question is, why does my function not work and is there a better way to get a random Int.
The simple answer is that you can't generate random numbers without invoking some amount of IO. Whenever you get the standard generator, you have to interact with the host operating system and it makes a new seed. Because of this, there is non-determinism with any function that generates random numbers (the function returns different values for the same inputs). It would be like wanting to be able to get input from STDIN from the user without it being in the IO monad.
Instead, you have a few options. You can write all your code that depends on a randomly generated value as pure functions and only perform the IO to get the standard generator in main or some similar function, or you can use the MonadRandom package that gives you a pre-built monad for managing random values. Since most every pure function in System.Random takes a generator and returns a tuple containing the random value and a new generator, the Rand monad abstracts this pattern out so that you don't have to worry about it. You can end up writing code like
import Control.Monad.Random hiding (Random)
type Random a = Rand StdGen a
rollDie :: Int -> Random Int
rollDie n = getRandomR (1, n)
d6 :: Random Int
d6 = rollDie 6
d20 :: Random Int
d20 = rollDie 20
magicMissile :: Random (Maybe Int)
magicMissile = do
roll <- d20
if roll > 15
then do
damage1 <- d6
damage2 <- d6
return $ Just (damage1 + damage2)
else return Nothing
main :: IO ()
main = do
putStrLn "I'm going to cast Magic Missile!"
result <- evalRandIO magicMissile
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
There's also an accompanying monad transformer, but I'd hold off on that until you have a good grasp on monads themselves. Compare this code to using System.Random:
rollDie :: Int -> StdGen -> (Int, StdGen)
rollDie n g = randomR (1, n) g
d6 :: StdGen -> (Int, StdGen)
d6 = rollDie 6
d20 :: StdGen -> (Int, StdGen)
d20 = rollDie 20
magicMissile :: StdGen -> (Maybe Int, StdGen)
magicMissile g =
let (roll, g1) = d20 g
(damage1, g2) = d6 g1
(damage2, g3) = d6 g2
in if roll > 15
then (Just $ damage1 + damage2, g3)
else Nothing
main :: IO ()
main = do
putStrLn "I'm going to case Magic Missile!"
g <- getStdGen
let (result, g1) = magicMissile g
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
Here we have to manually have to manage the state of the generator and we don't get the handy do-notation that makes our order of execution more clear (laziness helps in the second case, but it makes it more confusing). Manually managing this state is boring, tedious, and error prone. The Rand monad makes everything much easier, more clear, and reduces the chance for bugs. This is usually the preferred way to do random number generation in Haskell.
It is worth mentioning that you can actually "unwrap" an IO a value to just an a value, but you should not use this unless you are 100% sure you know what you're doing. There is a function called unsafePerformIO, and as the name suggests it is not safe to use. It exists in Haskell mainly for when you are interfacing with the FFI, such as with a C DLL. Any foreign function is presumed to perform IO by default, but if you know with absolute certainty that the function you're calling has no side effects, then it's safe to use unsafePerformIO. Any other time is just a bad idea, it can lead to some really strange behaviors in your code that are virtually impossible to track down.
I think the above is slightly misleading. If you use the state monad then you can do something like this:
acceptOrRejects :: Int -> Int -> [Double]
acceptOrRejects seed nIters =
evalState (replicateM nIters (sample stdUniform))
(pureMT $ fromIntegral seed)
See here for an extended example of usage:Markov Chain Monte Carlo