我一直在玩一些簡單的二進制編碼,它似乎大部分工作正常,直到我添加了狀態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