我一直在玩一些简单的二进制编码,它似乎大部分工作正常,直到我添加了状态monad。该计划是使用状态来保存我已经写入字节串的查找表,然后将偏移量写入以前的字符串实例,而不是重复它们。Haskell State Monad和Binary不会输出所有东西
我得到了所有类型的检查和运行,但后来我注意到它只写出链中的最终指令。我改为使用Control.Monad.State.Strict,但没有任何区别,所以我怀疑我在其他地方发生了根本性错误,但我不确定在哪里 - 我已将代码修剪成基本功能。另外,有没有更习惯于这样做的方式?
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import qualified Control.Monad.State.Strict as S
import Data.Binary.Put
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
data SState = SState {
wsPosition :: Int
-- plus whatever else
}
initialState = SState 0
type StatePut = S.State SState Put
class StateBinary a where
sput :: a -> StatePut
incPos :: Int -> S.State SState()
incPos amnt = do
(SState p) <- S.get
S.put $ SState (p + amnt)
writeSized :: Int -> (a -> Put) -> a -> StatePut
writeSized n f x = do
incPos n
return (f x)
writeInt32 :: Int -> StatePut
writeInt32 = writeSized 32 putWord32be . fromIntegral
writeBS :: BS.ByteString -> StatePut
writeBS b = writeSized (BS.length b) putByteString b
data SomeData = SomeData {
sdName :: BS.ByteString
, sdAge :: Int
, sdN :: Int
} deriving (Show, Eq)
instance StateBinary SomeData where
sput (SomeData nm a n) = do
writeBS nm
writeInt32 a
writeInt32 n
testData = SomeData "TestName" 30 100
runSPut :: StateBinary a => a -> BL.ByteString
runSPut a = runPut $ S.evalState (sput a) initialState
-- runSPut testData returns "\NUL\NUL\NULd"
什么是'writeSized',应该从哪里导入?此代码不适合我编译。 – bheklilr
对不起,我是批量复制粘贴,不小心跳过 - 现在加入! – Compo