我正在阅读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
值 . )
1 回答
我实际上在
eval1
的文档中看到了这个代码,它应该很好地检查(我重新缩进它):似乎
Map.lookup
之前做过更普遍的签名:http://hackage.haskell.org/package/containers-0.1.0.0/docs/Data-Map.html由于该文档的日期是2006年,并且仍然有上面引用的文本,说明
Map.lookup
具有更一般的签名,但在开头说一个脚注"Ported to newer GHC in 2012",我认为代码已更新但文本没有 .Edit:
我追溯了自2008年以来
Map.lookup
的变化历史:Code change,Trac ticket,Libraries list discussion