2

我需要从 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)

我想把它包装成某种状态单子,有类似的代码

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 源代码,但不完全理解发生了什么。

4

1 回答 1

2

这是 Monad Transformers 最典型的用例。

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

What functions should I implement? 
  • 好吧,您首先需要将Getmonad 包装到StateTTransformer 中以获取BitReader.
  • 您需要实现正确的定义以readBits用于get获取当前状态并将put状态保存回来。
  • 您需要运行包含的代码BitReader以获取GetMonad 中的输出。所以你需要定义runBitReaderusing 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 转换器的更多信息。

于 2012-09-13T16:40:01.910 回答