mat*_*thk 1 monads haskell state-monad
我想知道什么可以被视为关于Statemonad 的最佳实践.我也对任何其他建议持开放态度.
我有一个要解析的二进制文件.它包含需要解析的不同标头,以便能够读取整个文件.
因此,只能使用解析中的State来解析头文件.
data ParseState = ParseState {
offset :: Int64
buffer :: B.ByteString
endianness :: Endianness
pointerSize :: MachineWord
positionStack :: [Int64]
}
Run Code Online (Sandbox Code Playgroud)
然后将该数据用于Statemonad中
type Parser a = State ParseState a
Run Code Online (Sandbox Code Playgroud)
这可以完美地解决标头的解析.但是,只要我想解析整个文件,我需要标题中的信息才能正确读取文件.
data Header = Header {
txtOffset :: Int64,
stringOffset :: Int64
}
Run Code Online (Sandbox Code Playgroud)
我需要标头信息来继续解析文件.
我的想法是使用一个位于前一个状态之上的新状态monad.所以我有一个新的StateT monad:
type ParserFullState a = StateT Header (State ParserState) a
Run Code Online (Sandbox Code Playgroud)
因此,我可以继续使用新的状态转换器构建一整套解析器函数.我也可以采用不同的方式将标题添加到原始ParseState数据中.
我可以看到将标题添加回ParserState以下内容的优点如下:
lift来访问解析器原语.我能看到的缺点是:
你的建议是什么?我应该使用状态转换器吗?我应该将标头添加到原始状态还是其他任何情况?
谢谢.
一般来说,我建议不要使用多层State(或实际上任何变压器).变形金刚很棒,但在较厚的集群中,它们确实会让人感到困惑,特别是当类型系统无法正确决定MonadState使用哪个时.
然而,在你的具体情况下,另一个变换器实际上是一个好主意,但不是a StateT:在进一步解析文件时头文件信息不应该改变,所以它应该真的只是一个ReaderT,不应该吗?
type ParserFullState = ReaderT Header (State ParserState)
Run Code Online (Sandbox Code Playgroud)
或者等价的
type ParserFullState = RSS Header () ParserState
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
243 次 |
| 最近记录: |