Haskell 单子变形金刚。第一步
让我们考虑一下:Haskell 单子变形金刚。第一步,haskell,Haskell,让我们考虑一下: type Name = String -- variable names data Exp = Lit Integer -- expressions | Var Name | Plus Exp Exp | Abs Name Exp | App Exp Exp deriving (Show
type Name = String -- variable names
data Exp = Lit Integer -- expressions
| Var Name
| Plus Exp Exp
| Abs Name Exp
| App Exp Exp
deriving (Show)
data Value = IntVal Integer -- values
| FunVal Env Name Exp
deriving (Show)
type Env = Map.Map Name Value -- mapping from names to values
eval0 :: Env -> Exp -> Value
eval0 env (Var n) = fromJust (Map.lookup n env )
以上是0版本
现在,让我们考虑一元,1版本:
type Eval1 a = Identity a
eval1 :: Env -> Exp -> Eval1 Value
eval1 env (Var n) = Map.lookup n env
现在,作者说:
接下来,Var案例不再需要fromJust调用:
原因是Map.lookup被定义为在任何monad中工作
只需调用monad的fail函数,这与我们的
这里是一元公式。(Maybe monad的fail函数
不返回任何内容,而标识monad中的fail函数
引发异常,这将导致不同的错误消息。)
内容来自:
我也不清楚。请解释为什么引入monad Eval1可以让我们不关心来自just的
编辑:
现在,我试图编译它,我得到了错误,这个错误与我的直觉和我的怀疑是一致的。编者说:
Couldn't match type `Maybe Value' with `Identity Value'
Expected type: Eval1 Value
Actual type: Maybe Value
In the return type of a call of `Map.lookup'
In the expression: Map.lookup n env
In an equation for `eval1': eval1 env (Var n) = Map.lookup n env
那么,谁是对的,作者还是编译器,以及如何修复它
原因是Map.lookup被定义为在任何monad中工作,只需调用monad的fail函数
这不是真的。在文本中,Map.lookup
的定义与containers
package中的实际定义不同。作者将Map.lookup
推广到任何一元值,不仅可能
:
lookup' :: (Ord k, Monad m) => k -> Map k a -> m a
lookup' k m = case Map.lookup k m of
Nothing -> fail "some_error_message"
Just v -> return v
在撰写该草案时,Data.Map.lookup
显然对任何monad都有效。这不再是事实,但作者确实提供了本教程的一部分
具体来说,您必须检查结果可能字符串
值,并显式调用fail
-- Copied from the link above
eval1 env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env
我相信作者不久前是对的,lookup
用于返回任何monadm
的ma
。现在,lookup
只返回可能是a
。几周前当我读这篇文章时,我也有同样的问题。我确实找到了一个更新版本的文件(或至少是代码)来修复这个问题;我看看能不能找到链接。