CS 541 Lecture -*- Outline -*-
* Name binding and scope (have made a homework some years)
objective: to get across the notions of:
sugars (as way of explaining semantics)
and
simultaneous bindings
scope
Boil everything down to lambda and case
** pattern matching in function defs is sugar for case (Davie pp. 29 and 190)
Q: How could one define the semantics of Haskell function defs
with complex features like guards and pattern matching?
One way
------------------------------------------
FUNCTION DEFINITION SEMANTICS
The problem: function defs can be complex
> fact 0 = 1
> fact n | n > 0 = n * fact(n-1)
> while test f x
> | b = while test f (f x)
> | otherwise = x
> where b = test x
> quotient(i,j) = lastq
> where (lasti,lastq) =
> (while notdone xform (i,0))
> notdone (i,q) = (i >= j)
> xform (i,q) = (i-j,q+1)
what does this all mean?
------------------------------------------
Q: What features are being used?
We'd like an explanation for each feature that is:
- syntax-directed (based on the syntax),
like a yacc-based compiler
and
- "adds up" to an explanation for the whole thing
Such an explanation is *compositional*.
(this is unlike English)
compositional vs. Non-compositional examples:
red book, red ball vs. red herring, red neck,
hockey player, baseball player vs. CD player
day room, dark room vs. rest room
pro vs. con ==> progress vs. congress (;->)
train station, bus station vs. work station (;->)
------------------------------------------
SYNTACTIC SUGARS
AN EXPLANATORY DEVICE
def: a feature of a language is
a *syntactic sugar* if
Example:
fact 0 = 1
fact n | n > 0 = n * fact(n-1)
==>
------------------------------------------
... each occurrence of that syntax can be regarded as macro call
and replaced by some other piece of syntax
... fact = (\ x -> (case x of
0 -> 1
n -> if n > 0 then n * fact(n-1)
else error "Unmatched pattern"))
discuss the meaning of the case,
pattern match from the top
------------------------------------------
PATTERN GUARDS SUGAR FOR IF (D 2.7.1)
Guard desugaring:
| 1 = 1
| 2 = 2
...
| n = n
where { }
==>
FOR YOU TO DO
Desugar:
while test f x
| b = while test f (f x)
| otherwise = x
where b = test x
------------------------------------------
... = let in
if 1 then 1 else
if 2 then 2 else
...
if n then n else error "Unmatched guard"
------------------------------------------
SYNTACTIC SUGAR FOR IF
if 1 then 2 else 3
==>
case 1 of
True -> 2
False -> 3
------------------------------------------
------------------------------------------
MULTIPLE BINDING IS SUGAR FOR CASE
Function binding form:
11 ...
1n = 1
...
m1 ...
mn = m
==>
FOR YOU TO DO
desugar the following
> name 0 = "zero"
> name 1 = "one"
> name n = "many"
------------------------------------------
...
x1 ... xn =
case (x1,...,xn) of
(11, ...
1n) -> 1
...
(m1, ...
mn) -> m
(where x1 ... xn are fresh)
------------------------------------------
FUNCTION DEFINITION SUGAR FOR LAMBDA
x1 ... xn = E
==>
Example:
compose (f,g) x = f (g x)
==>
------------------------------------------
... x1 ... xn-1 = (\ xn -> E)
and so get
= (\x1 -> (...(\xn -> E)...))
... compose = (\(f,g) -> (\x -> f (g x)))
Now patterns only occur in case expressions and lambdas
------------------------------------------
GETTING PATTERNS OUT OF LAMBDAS
ucompose (f,g) x = f (g x)
==>
ucompose = \ (f,g) -> \ x -> f (g x)
==>
------------------------------------------
ucompose = \ fg ->
case fg of
(f,g) -> \x -> f (g x)
** simultaneous binding, lexical scope (D 2.4)
------------------------------------------
SCOPE FOR DECLARATIONS AND LET
> x = u + v
> y = u - v
> (u,v) = (4,5) :: (Integer, Integer)
let x1 = u1 + v
y1 = u1 - v
u1 = 4 :: Integer
in [x1,y1,u1,v]
------------------------------------------
draw contour for scope of x,y,u,v
includes all of the parts of the program after the =
draw contour for scope of x1,y1,u1
includes the right-hand sides and the body (like letrec)
Q: What's this like in Scheme?
Q: What will that expression's value be?
everything is lazy, order doesn't matter.
then bindings made simultaneously
------------------------------------------
SYNTACTIC SUGAR FOR LET
(dynamic behavior, not typing)
let 1 = 1
...
n = n
in 0
==>
let (~1, ..., ~
n) =
(1, ..., n) in 0
let = 1 in 0
==>
let = fix (\ ~
-> 1)
in 0
let = 1 in 0
-- if no var in occurs
-- free in 1
==>
------------------------------------------
... (\ ~ -> 0) 1
This last is like Scheme let,
and even it gets desugared to a case...
The ~ makes an irrefutable binding: that is, a lazy one
compare scope of result with the original scope.
** Binding vs. assignment (skip)
in Haskell, only bindings, no changes to existing bindings,
but can make holes in their scope.
=> referential transparency
:=, assignment
binds name to cell,
no referential transparency
what's bound to what:
name bound to value, because 3 may be value of several names
the binding is a property of the name (not 3)