我正在阅读Monad Transformer文件。 我遇到过这个代码示例:
import qualified Data.Map as Map
import Control.Monad.Identity
type Eval1 a = Identity a
runEval1 :: Eval1 a -> a
runEval1 ev = runIdentity ev
type Name = String
data Exp = Lit Integer
| Var Name
| Plus Exp Exp
| Abs Name Exp
| App Exp Exp
deriving (Show)
data Value = IntVal Integer
| FunVal Env Name Exp
type Env = Map.Map Name Value
他们为此写了评价函数:
eval0 :: Env -> Exp -> Value
eval0 env (Var i) = fromJust $ Map.lookup i env
另一种具有monadic风格的评估函数:
eval1 :: Env -> Exp -> Eval1 Value
eval1 env (Var n) = Map.lookup n env
(我只是展示了我遇到问题的eval1
函数的一部分)
eval0
函数类型检查但eval1
没有进行类型检查。那个文件中的错误是这样,还是我错过了什么?
他们继续解释eval1
这样的话:
Var case不再需要fromJust调用了:原因是这样的 Map.lookup被定义为只需调用它就可以在任何monad中工作 monad的失败功能 - 这与我们的monadic配方非常吻合 这里。 (Maybe monad的失败功能返回Nothing,而 Identity monad中的失败函数抛出异常,即 将导致不同的错误消息。)
但Map.lookup
是否定义为与任何monad一起使用? (它的类型签名表示它返回Maybe
值。)
答案 0 :(得分:4)
我实际上在eval1
的文档中看到了这段代码,应该检查好(我重新缩进):
eval1 env (Var n) =
maybe (fail ("undefined variable: " ++ n)) return $
Map.lookup n env
Map.lookup
之前的行为似乎有更一般的签名:http://hackage.haskell.org/package/containers-0.1.0.0/docs/Data-Map.html
由于该文件的历史可以追溯到2006年,并且仍然有上面引用的文字说明Map.lookup
具有更一般的签名,但在开头的一个脚注中说“在2012年移植到更新的GHC”,我认为代码已更新,但文本没有。
修改强>
我追溯了Map.lookup
的变化历史,可追溯到2008年:Code change,Trac ticket,Libraries list discussion