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
Getmonad into theStateTTransformer to getBitReader.readBitsusinggetto get the current state andputto save the state back.BitReaderto get back the output inGetMonad. So you need to definerunBitReaderusingrunStateT.To answer your next question.
I have given the possible implementation. You still need to define some functions to make it work.
I don’t know how looking into code of
Getwas going to help you. You were looking in the wrong house. You need to read aboutState MonadsandMonad Transformers.You can read more about monad transformers here.