CS571 sp24 Lecture15
CS571 sp24 Lecture15
fact 3
Building Bigger Programs
let x = 3 + 2 in
let y = 4 in
x+y
Is Similar to…
is similar to C code:
{ int x = 3+2;
{ int y = 4;
return x+y;
}
}
No Mutation
• let x = 3 + 2 in let x = 4 in x
is similar to C code:
{ int x = 3+2;
{ int x = 4;
return x;
}
}
• let x = 3 + 2 in (let x = 4 in x) + x
let…in… Expression
• The let expression provides a way to bind names to
values/expressions.
let x = 3 + 2 in x^2
• The binding also allows for encoding top-level function definitions
into directly evaluable expressions.
let inc x = x + 1 in inc 2
• Nested let expressions provide continuation, i.e. “stringing
expressions together”
let x = 3 + 2 in let y = 4 in x^2 + y
let…in… Expression (Cont.)
• One might think it is the same as assignments in C-like languages, but
note that let-bindings are immutable (so much so that some purists don’t
call “x” or “y” as variables…)
• The expression also introduces non-global scoping: it is also possible to
make definitions local to the expression.
f y = let x=3+2 in x^2+y
f 1 giving the result 26.
Main> factorial 4
24
fact x
| x < 0 = error “negative value”
| x == 0 = 1
| otherwise = x * fact (x-1)
… > : t fact
fact :: (Ord a, Num a) => a a
The input must be in the intersection of classes Ord (Bool, Char, Int, Integer, Float, Double etc.)
and Num.
…> fact 3.7
Program error: negative value
Factorial Revisited
| x == 0 = 1
| otherwise = x * factorial (x – 1)
Factorial Revisited Revisited
factorial 0 = 1
factorial x = x * factorial (x – 1)
Functional Programming Basics:
Summary
• All programs are functions
• Control Flow
• If statements
• Guards
• Case statements
• Multiple definitions
Key Concepts in Functional
Programming
• Higher-order functions & closures
• Laziness
• Call-by-name vs. call-by-value
Higher-order functions
& Closures
Functions as Values
• Takes a function as an argument or returns a function as a result, or
both
map f [x1,x2,x3]
= f x1 : map f [x2,x3]
= f x1 : f x2 : map f [x3]
= f x1 : f x2 : f x3 : map f []
= f x1 : f x2 : f x3 : []
Higher-Order Function: map
doubleAll [] = []
doubleAll (x:xs) = 2*x : doubleAll xs
map f [] = []
map f (x:xs) = f x : map f xs
double x = 2*x
doubleAll xs = map double xs
squareAndAdd x y =
squareAndAdd x = let x2 = x * x in
let x2 = x * x in x + y
\y -> x2 + y
squareThreeAndAdd = squareAndAdd 3
squareThreeAndAdd 1
squareThreeAndAdd 2 Outputs 10
Outputs 11
Where is the “hidden information” that x = 3 stored?
How to Read this Exactly?
• Laziness Example
Lazy Evaluation
takeVal (naturalsLargerThan 1) 5
= (head (naturalsLargerThan 1)) : takeVal ...
= (head (1 : naturalsLargerThan(1+1)) : takeVal ...
= 1 : takeVal ...
= 1 : takeVal (tail (naturalsLargerThan 1)) 4
= 1 : head (tail (naturalsLargerThan 1)) : takeVal ...
= 1 : head (naturalsLargerThan (1+1)) : takeVal ...
= 1 : head (naturalsLargerThan (2)) : takeVal ...
= 1 : head (2 : naturalsLargerThan(2+1)) : takeVal ...
= 1 : 2 : takeVal ...
= ...
= 1 : 2 : 3 : 4 : 5
Lazy Execution Model
Capture Avoiding Substitution
• To execute (\x. A) (B), replace it with the expression A with all
instances of x in A substituted to B
• E.g. (\x. x + 1) 3 => 3 + 1 => 4
We use ⊥ (bottom) to denote the “value” of expressions that do not terminate or that error.
Revisiting Parameter Passing
let x = x + 1 in
✅ ❌
4+2
let x = x + 1 in
True || x == 5 ✅ ❌
let x = \y -> (x y) + 1 in
4+2 ✅ ✅
let x = \y -> (x y) + 1 in
✅ ¯\_( ツ )_/¯
True || (x 0) == 5
let x = x + 1 in
x == 5 ❌ ❌
Acknowledgments
• William Hallahan
• David Liu
• Zerksis Umrigar