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
用于返回任何monad
m
ma
。现在,
lookup
只返回
可能是a
。几周前当我读这篇文章时,我也有同样的问题。我确实找到了一个更新版本的文件(或至少是代码)来修复这个问题;我看看能不能找到链接。