我需要从Get monad读取一些位。现在我的代码看起来像
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)
我想将它包装成某种状态monad,以便像
这样的代码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)
我应该实施哪些功能?它们应该如何实施?
我已经研究过Get和BitGet源代码,但还没有完全理解发生了什么。
答案 0 :(得分:2)
这是Monad变形金刚最典型的用例。
您已正确定义了大部分结构。回答你的问题
What functions should I implement?
Get
monad包装到StateT
Transformer中以获取BitReader
。readBits
为get
实现正确的定义以获取当前状态,并put
将状态保存回来。BitReader
中的代码以获取Get
Monad中的输出。因此,您需要使用runBitReader
定义runStateT
。回答你的下一个问题。
How should they be implemented?
我已经给出了可能的实施方案。您仍然需要定义一些函数才能使其工作。
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)
我不知道如何查看Get
的代码会对您有所帮助。你在找错了房子。您需要了解State Monads
和Monad Transformers
。
您可以阅读有关monad变换器here的更多信息。