从Monad读取位的Monadic方法

时间:2012-09-13 15:21:24

标签: haskell state-monad

我需要从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源代码,但还没有完全理解发生了什么。

1 个答案:

答案 0 :(得分:2)

这是Monad变形金刚最典型的用例。

您已正确定义了大部分结构。回答你的问题

What functions should I implement? 
  • 您首先需要将Get monad包装到StateT Transformer中以获取BitReader
  • 您需要使用readBitsget实现正确的定义以获取当前状态,并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 MonadsMonad Transformers

您可以阅读有关monad变换器here的更多信息。