我正在Haskell中编写解释器,我有map:name_of_function - >定义功能。
<form method="post">
<input type="text" name="myText" />
<input type="submit" name="ask" class="tbutton" value="ask" />
</form>
<?php
if(isset($_POST['ask'])){
echo($_POST['myText']);
}
?>
我的翻译monad:
Map String Defun
正如你所看到的,“最后一个”monad是type InterpreterMonad = StateT (EnvFun, (Stack EnvEval)) (ErrorT String IO ) ()
。
现在,当我想处理调用函数时:
ErroT
正如您所见,我必须使用 handleFCall :: Stmt -> InterpreterMonad
handleFCall (VarName name) args = get >>= \(envFun, contextStack) -> case (Map.lookup (VarName name) envFun) of
Nothing -> throwError "Err"
(Just x) -> DoSthOther
。不过我使用的是case
,所以我想在这里避免使用>>=
。但是,case of
返回Map.lookup
失败,我想添加错误消息。
我没有Haskell的经验所以我不知道如何处理它。更重要的是,欢迎对我的代码提出批评。
干杯。
答案 0 :(得分:4)
使用case语句没有错,虽然使用do notation重新格式化,你的函数看起来更像
handleFCall (VarName name) args = do
(envFun, contextStack) <- get
case Map.lookup (VarName name) envFun of
Nothing -> throwError "Err"
Just x -> doSthOther x
其他Haskell程序员会更熟悉。但是,如果您真的想避免使用案例,只需使用maybe
函数:
handleFCall (VarName name) args = do
(envFun, contextStack) <- get
maybe (throwError "Err") doSthOther $ Map.lookup (VarName name) envFun
或>>=
handleFCall (VarName name) args
= get >>=
(\(envFun, contextStack) ->
maybe (throwError "Err") doSthOther
$ Map.lookup (VarName name) envFun
)
但我个人觉得案例陈述更具可读性。
答案 1 :(得分:1)
errors
package在Control.Error.Util
中有以下操作(并从Control.Error
重新导出):
-- You can turn `Maybe` into `Either` by supplying a constant to use
-- for the `Left` case.
note :: a -> Maybe b -> Either a b
-- Ditto for `MaybeT` and `ExceptT`
noteT :: Monad m => a -> MaybeT m b -> ExceptT a m b
-- And there are useful shortcuts for other combinations
failWith :: Applicative m => e -> Maybe a -> ExceptT e m a
failWith
特别看起来在这里非常适合,像这样的表达式就可以了。
failWith "Err" (Map.lookup (VarName name) envFun)
请注意,您在示例中使用的ErrorT
转换器已被弃用,而不是ExceptT
(因为上面的签名正在使用),所以您必须相应地更改您的代码以使用errors
包。另一方面,这些功能非常简单,如果您愿意,可以自己烘焙。