In Phil Wadler's paper : The essence of functional programming, Wadler describes the application of Monads using a simple interpreter program. The program is as shown below:
A term is either a variable, a constant, a sum, a lambda expression, or an application. The following will serve as test data.
term0 = (App (Lam "x" (Add (Var "x") (Var "x"))) (Add (Con 10) (Con 11)))
For our purposes, a monad is a triple
(M,unitM,bindM)
consisting of a type constructorM
and a pair of polymorphic functions.unitM :: a -> M a bindM :: M a -> (a -> M b) -> M b
Then the interpreter program is described as:
type Name = String
data Value = Wrong
| Num Int
| Fun (Value -> M Value)
I do not see how M Value
has been included here. My understanding that Haskell does not allow type constraints on data type constructors?
Further details: The complete program is below:
type Name = String
data Term = Var Name
| Con Int
| Add Term Term
| Lam Name Term
| App Term Term
data Value = Wrong
| Num Int
| Fun (Value -> M Value)
type Environment = [(Name, Value)]
interp :: Term -> Environment -> M Value
interp (Var x) e = lookup x e
interp (Con i) e = unitM (Num i)
interp (Add u v) e = interp u e `bindM` (\a ->
interp v e `bindM` (\b ->
add a b))
interp (Lam x v) e = unitM (Fun (\a -> interp v ((x,a):e)))
interp (App t u) e = interp t e `bindM` (\f ->
interp u e `bindM` (\a ->
apply f a))
lookup :: Name -> Environment -> M Value
lookup x [] = unitM Wrong
lookup x ((y,b):e) = if x==y then unitM b else lookup x e
add :: Value -> Value -> M Value
add (Num i) (Num j) = unitM (Num (i+j))
add a b = unitM Wrong
apply :: Value -> Value -> M Value
apply (Fun k) a = k a
apply f a = unitM Wrong
As can be seen
interp (Lam x v) e = unitM (Fun (\a -> interp v ((x,a):e)))
requires definition data Value = ... | Func (Value -> M Value)
I tried to implement interp (Lam x v)
by using data Value = ... | Func (Value -> Value)
, but it did not seem possible to me.
M is not a constraint, it is a type constructor. So writing
M Value
is similar[Value]
,Maybe Value
etc. A constraint would be something likeMonad m => m Value
, where m is a type variable, not a type constructor andMonad m
is the constraint (Monad is a type class).In the paper, the definition of the type
M value
has not been presented, and it is later shown that you can give it different definitions (the definitions would involve definingdata M v = ...
and the functionsbindM
andunitM
).Edit: If you wanted to have a constraint, you would change the definition of value like this:
And then have the constraint in the types of functions, e.g.: