【发布时间】:2019-12-09 01:58:33
【问题描述】:
目标
我正在尝试编写解释器的内部结构,出于人体工程学的目的,我想我想要一个可以像 state 和任何一个 monad 一样工作的 monad。
例如,我想用任何一种风格做一些事情:
checkedAddress :: Integer -> Interpreter Int
checkedAddress n = if (n < toInteger (minBound :: Int))
then fail $ "Address " ++ show n ++ " is too low"
else if (n > toInteger (maxBound :: Int))
then fail $ "Address " ++ show n ++ " is too high"
else return $ fromInteger n
我想用状态样式做其他事情:
setInstructionPointer :: Int -> Interpreter ()
setInstructionPointer ip (Machine _ mem) = ((), Machine ip mem)
getInstructionPointer :: Interpreter Int
getInstructionPointer m@(Machine ip mem) = (ip, m)
问题
是否可以像这样创建一个 state-either 混合 monad?
如果不可能,为什么不可能?是否有替代方案具有良好的人体工程学设计,并且我认为提前终止(例如通过Left m >>= _ = Left m 停止进一步处理)这种方法的效率?
如果可能的话,我该如何为该类型编写 monad 实例?我试过了,但是在写(>>=) 的时候卡住了,因为我看不到在不知道运行时Machine 值的情况下知道要生成什么构造函数的方法。
data Interpreter a = Running (Machine -> (a, Machine))
| Halted (Machine -> Machine)
| Error String (Machine -> Machine)
instance Monad Interpreter where
return = Running . (,)
Running f >>= g = DontKnowWhich $ \ m -> let (a, m') = f m
in case g a of
Running h ->
Halted h ->
Error s h ->
h@(Halted _) >>= _ = h
e@(Error _ _) >>= _ = e
【问题讨论】:
-
你需要的是一个单子转换器。查看 mtl 包中的 StateT 和 EitherT。
标签: haskell monads state-monad either