3
votes

I'm reading through the Monad Transformer document. And I have come across this code sample:

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

And they write evaluation function for that:

eval0 :: Env -> Exp -> Value
eval0 env (Var i) = fromJust $ Map.lookup i env

And another evaluation function with monadic style:

eval1 :: Env -> Exp -> Eval1 Value
eval1 env (Var n) = Map.lookup n env 

(I'm just showing part of the eval1 function where I have problem)

The eval0 function typechecks but eval1 doesn't typecheck. So is this error in that document or am I missing something ?

Also they go on explaining about eval1 like this:

Var case does not need a fromJust call anymore: The reason is that Map.lookup is defined to work within any monad by simply calling the monad’s fail function – this fits nicely with our monadic formulation here. (The fail function of the Maybe monad returns Nothing, whereas the fail function in the Identity monad throws an exception, which will lead to different error messages.)

But is Map.lookup defined to work with any monad ? (It's type signature indicates that it retuns a Maybe value.)

1

1 Answers

4
votes

I actually see this code in the document for eval1, which should typecheck fine (I re-indented it):

eval1 env (Var n) =
    maybe (fail ("undefined variable: " ++ n)) return $
        Map.lookup n env

It seems that Map.lookup did earlier have the more general signature: http://hackage.haskell.org/package/containers-0.1.0.0/docs/Data-Map.html

Since the document dates from 2006 and still has the text you quote above stating that Map.lookup has the more general signature, but a footnote at the beginning saying "Ported to newer GHC in 2012", I think that the code has been updated but the text hasn't.

Edit:

I tracked down the history of the change in Map.lookup, dating from 2008: Code change, Trac ticket, Libraries list discussion