我有功能:
step :: forall m . (MonadState IntCodeState m) => m (Maybe ())
Run Code Online (Sandbox Code Playgroud)
当我do在函数体中使用符号时,它m用作 monad。正如您所料,我实际上希望它使用m Maybe. 但是,它不明白这m Maybe是一个单子。我如何向 Haskell 表达这一点?
编辑:目前这可能有点格式错误。具体类型应该是
StateT IntCodeState Maybe (),但我试图不声明具体类型,所以问题是:我该如何声明?
编辑 2:另一个尝试:我有一些看起来像这样的函数:
getValueIndex :: (MonadState IntCodeState m) => Int -> m (Maybe Int)
Run Code Online (Sandbox Code Playgroud)
在这里,我正在研究 state monad 的级别。但是,我现在希望能够“好像”m Maybe是 monad。我希望这很简单,但我想不出一种表达方式。我想写的代码是这样的
step :: forall m . (MonadState IntCodeState m) => m (Maybe ())
step = do
full <- opCode
let len = length (snd full) + 1
process full <* (next += len)
Run Code Online (Sandbox Code Playgroud)
但是 opCode 返回一个m (Maybe a),我想full成为一个a
但是 opCode 返回一个
m (Maybe a),我想full成为一个a
看起来您想使用引擎盖下的MaybeT monad 转换器,m (Maybe a)其Monad实例可以满足您的需求:
MaybeT monad 转换器扩展了 monad,使其能够在不返回值的情况下退出计算。
只有当序列中的所有动作都执行时,动作序列才会产生值。如果退出,则跳过序列的其余部分并退出复合动作。
以下是类型:
MaybeT :: m (Maybe a) -> MaybeT m a
runMaybeT :: MaybeT m a -> m (Maybe a)
Run Code Online (Sandbox Code Playgroud)
这也将很有帮助,专门来自MonadTrans:
lift :: m a -> MaybeT m a
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下:
step :: forall m . (MonadState IntCodeState m) => m (Maybe ())
step = runMaybeT $ do
full <- MaybeT opCode -- :: MaybeT opCode :: MaybeT m a, full :: a
let len = length (snd full) + 1
lift $ process full <* (next += len)
Run Code Online (Sandbox Code Playgroud)
我假设process返回 anm ()并用于lift将其更改为MaybeT m ().