나는 간단한 바이너리 인코딩으로 놀아 왔으며, 대부분 모나드를 추가하기 전까지는 제대로 작동하는 것처럼 보였다. 현재 상태를 사용하여 내가 지금까지 작성한 것에 대한 룩업 테이블을 유지하고 문자열의 이전 인스턴스에 오프셋을 복사하여 복제하지 않고 작성합니다.하스켈 스테이트 모나드와 바이너리가 모든 것을 출력하지 않는다.
나는 체크하고 실행하는 모든 타입을 얻었지만, 체인에서 최종 명령을 쓰는 것만 알았다. 나는 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