I’m building a call by name Haskell interpreter and I want to implement a function short :: Val -> Exp -> Error Val that will evaluate a value applied to an expression. I don’t want to evaluate the second arguments of the short-circuited boolean binary operators (i.e. ((&&) False) and ((||) True)), nor the argument passed to a unit lambda (\() -> ...) abstraction.
In a lazy language such as Haskell, I know you get short circuited boolean binary operators built into the Prelude. I was thinking that its possible to do something like this:
short :: Val -> Exp -> Error Val
short (Partial (&&) False) = False
-- Making use of Partial Oper Val that is defined in Val
But I already know that a type error will arise. I’m not sure what to exactly do. Any suggestions?
Some additional definitions:
data Val = VUnit | VNil
| VN Int | VB Bool | VOp Oper
| Partial Oper Val
| VLamUnit Exp (Env Val)
| VLam String Exp (Env Val)
| VListBool [Bool]
| VListInt [Int]
data Exp = Unit | Nil
| N Int | B Bool | Var String | Op Oper
| App Exp Exp
| LamUnit Exp
| Lam String Exp
| If Exp Exp Exp
| Let [(String, Exp)] Exp
data Error a = S a
| Error String
The evaluation of the arguments of a function is first determined by the patterns used to bind the arguments.
If you have
no evaluation takes place on binding the arguments, since the patterns are irrefutable variable patterns,
valis – partially or maybe completely – evaluated to determine the outcome of the first guard. If that evaluates toTrue,expis only evaluated if it is used insomethingand its evaluation is necessary to evaluatesomething. Only if the first two conditions evaluate toFalse,exis evaluated to determine the value of the third guard (and maybe not even then).If you can shortcut based on the constructor of
val, you can use a refutable pattern forvaland letexbe a variable pattern (just an identifier), you get the same short-circuiting as for(&&)etc.If you don’t use the
Expargument on the right hand side, you don’t even need to give it a name, the wildcard_says “here is an argument that shall be ignored”.For your desired behaviour of
that as such doesn’t work because
Falseis aBooland not aVal, you can usewith a hypothetical constructor
ORofOper. (You can use(&&)there, but that is a variable pattern matching anything.) That pattern doesn’t even bind theExpargument, so unless its evaluation has been forced by previous equations forshort, it remains unevaluated.