HaskellYu Zhang
Acknowledgement: modified from Stanford CS242 https://courseware.stanford.edu/pg/courses/317431/
Course web site: http://staff.ustc.edu.cn/~yuzhang/fpl
Spring 2013
2
Reading
“Concepts in Programming Languages”Chapter 5https://courseware.stanford.edu/mod/file/download.php?file_guid=96710
“Real World Haskell”http://book.realworldhaskell.org/ https://rwh.readthedocs.org
Others● http://haskell.org/ghc/docs/latest/html/libraries/● Books&tutorials: http://haskell.org/haskellwiki/Books_and_tutorials● Research papers: http://haskell.org/haskellwiki/Research_papers ● Bloggers: http://haskell.org/haskellwiki/Blog_articles
3
Language Evolution
Algol 60
Algol 68
ML Modula
Lisp
Pascal
Haskell
C
C++
Smalltalk
Java
Many others: Algol 58, Algol W, Fortran, Ada, Perl, Python, Ruby, C#, Javascript, F#...
4
C Programming Language
● Dennis Ritchie, ACM Turing Award for Unix● Statically typed, general purpose systems programming
language● Computational model reflects underlying machine● Relationship between arrays and pointers
– An array is treated as a pointer to first element– E1[E2] is equivalent to ptr dereference: *((E1)+(E2))– Pointer arithmetic is not common in other languages
● Not statically type safe– If variable has type float, no guarantee value is floating pt
● Ritchie quote– “C is quirky, flawed, and a tremendous success”
5
ML programming language● Statically typed, general-purpose programming language
– “Meta-Language” of the LCF theorem proving system● Type safe, with formal semantics● Compiled language, but intended for interactive use● Combination of Lisp and Algol-like features
– Expression-oriented– Higher-order functions– Garbage collection– Abstract data types– Module system– Exceptions
● Used in printed textbook as example language
Robin Milner, ACM Turing-Award for ML, LCF Theorem Prover, ...
6
Haskell
● Haskell programming language is– Similar to ML: general-purpose, strongly typed, higher-order,
functional, supports type inference, interactive and compiled use– Different from ML: lazy evaluation, purely functional
core, rapidly evolving type system● Designed by committee in 80’s and 90’s to unify
research efforts in lazy languages– Haskell 1.0 in 1990, Haskell ‘98, Haskell’ ongoing– “A History of Haskell: Being Lazy with Class” HOPL 3
Paul Hudak
John Hughes
SimonPeyton Jones
Philip Wadler
7
Haskell B Curry
● Combinatory logic– Influenced by Russell and Whitehead– Developed combinators to represent
substitution– Alternate form of lambda calculus that
has been used in implementation structures
● Type inference– Devised by Curry and Feys– Extended by Hindley, Milner
Although “Currying” and “Curried functions” are named after Curry, the idea was invented by Schoenfinkel earlier
8
Why Study Haskell?
● Good vehicle for studying language concepts● Types and type checking
– General issues in static and dynamic typing– Type inference– Parametric polymorphism– Ad hoc polymorphism (aka, overloading)
● Control– Lazy vs. eager evaluation– Tail recursion and continuations– Precise management of effects
9
Why Study Haskell?
● Functional programming will make you thinkdifferently about programming.– Mainstream languages are all about state– Functional programming is all about values
● Haskell is “cutting edge”– A lot of current research is done using Haskell– Rise of multi-core, parallel programming likely to make
minimizing state much more important● New ideas can help make you a better
programmer, in any language
10
Most Research Languages
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The quick death
Geeks
Pra
ctit
ioners
11
Successful Research Languages
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The slow death
Geeks
Pra
ctit
ion
ers
12
C++, Java, Perl, Ruby
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000 The complete absence of death
Geeks
Pra
ctit
ioners Threshold of immortality
13
Haskell
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The second life?
Geeks
Pra
ctit
ioners
“Learning Haskell is a great way of training yourself to think
functionally so you are ready to take full advantage of C# 3.0
when it comes out” (blog Apr 2007)
“I'm already looking at coding problems and my
mental perspective is now shifting back and forth between purely OO and
more FP styled solutions” (blog Mar 2007)
14
Haskell Implementation
● The Haskell Platform for Windows, Mac OS, Linux– First get and install Glasgow Haskell Compiler 7.4.2
http://www.haskell.org/ghc/ ./configure && sudo make install
– Install OpenGL utility toolkitsudo apt-get install freeglut3 freeglut3-dev
– Install the Haskell Platform 2012.4.0.0http://www.haskell.org/platform
./configure && make && sudo make install– Interactive
ghci or ghci intro.hs– Compiled
ghc -make intro.hs ./intro
15
Function Types in Haskell
● In Haskell, f :: A → B means for every x ∈ A,
f(x) = some element y = f(x) ∈ B
run forever
In words, “if f(x) terminates, then f(x) ∈ B.”
● In ML, functions with type A → B can throw an exception or have other effects, but not in Haskell
16
Higher-Order Functions● Functions that take other functions as arguments or return
as a result are higher-order functions.● Common Examples:
– Map: applies argument function to each element in a collection.– Reduce: takes a collection, an initial value, and a function, and
combines the elements in the collection according to the function.
● Google uses Map/Reduce to parallelize and distribute massive data processing tasks. (Dean & Ghemawat, OSDI 2004)
17
Basic Overview of Haskell
● Interactive Interpreter (ghci): read-eval-print– ghci infers type before compiling or executing
Type system does not allow casts or other loopholes!● Examples
Prelude> :set +t // print type after evaluationPrelude>(5+3)-26it :: IntegerPrelude> if 5>3 then “Harry” else “Hermione”“Harry”it :: [Char] -- String is equivalent to [Char]Prelude> 5==4Falseit :: Bool
● Prelude>:set +m // allow multiline commands● Prelude>:help
18
Overview by Type
● BooleansTrue, False :: Boolif ... then ... else … --types must match
● Integers0, 1, 2, ... :: Integer+, * , ...:: Integer-> Integer -> Integer
● Strings“Ron Weasley” :: [Char]
● String is a synonym for the type [Char]● Floats
1.0, 2.0, 3.14159, …:: Double
http://haskell.org/ghc/docs/latest/html/libraries/
19
Simple Compound Types
● Tuples(4, 5, “Griffendor”) :: (Integer, Integer, String)
● Lists[ ] :: [a] -- polymorphic type1 : [2, 3, 4] :: [Integer] -- infix cons notation
● Recordsdata Person = Person {firstName :: String, lastName :: String}
deriving (Eq, Ord, Show, Read)let hg = Person { firstName = “Hermione”, lastName = “Granger”}hg::Person
20
Patterns and Declarations
● Patterns can be used in place of variables<pat> ::= <var> | <tuple> | <cons> | <record> ...
● Value declarations– General form: <pat> = <exp>
let <pat> = <exp> // in ghci● ghci only accepts a highly restricted subset of Haskell
– ExamplesmyTuple = (“Flitwick”, “Snape”)(x,y) = myTuplemyList = [1, 2, 3, 4]z:zs = myList
– Local declarationslet (x,y) = (2, “Snape”) in x * 4
In ghci, you need input:● Prelude> let myTuple = …● Prelude> let (x,y) = …
Or you can save the left code into a file, e.g. ex.hs, then in ghci, you can input:● Prelude> :load ex.hs● Prelude>myTuple
21
Functions and Pattern Matching● Anonymous function
\x -> x+1 --like Lisp lambda, function (...) in JS● Function declaration form
<fname> <pat1> = <exp1>...<fname> <patn> = <expn> // default form in the slides
– In ghci,let { <fname> <pat> = <exp>;...; <fname> <pat> = <exp>}
● Examplesf (x,y) = x+y --argument must match pattern (x,y)length [ ] = 0length (x:s) = 1 + length(s)f :: Num a => (a, a) → a length :: Num a => [t] → a
22
Map Function on Lists
● Apply function to every element of listmap f [ ] = [ ]map f (x:xs) = f x : map f xs
– map :: (t → a) → [t] → [a]map (\x -> x+1) [1,2,3] // [2,3,4]
● Compare to Lisp(define map (lambda (f xs) (if (eq? xs ()) () (cons (f (car xs)) ((map f (cdr xs))))))
24
More Efficient Reverse
reverse xs = let rev ( [ ], accum ) = accum rev ( y:ys, accum ) = rev ( ys, y:accum ) in rev ( xs, [ ] )
1
2
3 1
2
3 1
2
3 1
2
3
25
List Comprehensions
● Notation for constructing new lists from old:myData = [1,2,3,4,5,6,7]twiceData = [2 * x | x <- myData] -- [2,4,6,8,10,12,14]twiceEvenData = [2 * x| x <- myData, x `mod` 2 == 0]
-- [4,8,12]● Similar to “set comprehension”
{ x | x ∈ Odd ∧ x > 6 }
26
Datatype Declarations
● Examplesdata Color = Red | Yellow | Blue
● elements are Red, Yellow, Blue
data Atom = Atom String | Number Int● elements are Atom “A”, Atom “B”, ..., Number 0, ...
data List = Nil | Cons (Atom, List)● elements are Nil, Cons(Atom “A”, Nil), ...● Cons(Number 2, Cons(Atom(“Bill”), Nil)), ...
● General formdata <name> = <clause> | ... | <clause><clause> ::= <constructor> | <contructor> <type>
● Type name and constructors must be Capitalized.
27
Datatypes and Pattern Matching
● Recursively defined data structuredata Tree = Leaf Int | Node (Int, Tree, Tree) deriving (Eq, Show, Read)Node(4, Node(3, Leaf 1, Leaf 2), Node(5, Leaf 6, Leaf 7))
● Recursive functionsum::Tree → Int sum (Leaf n) = nsum (Node(n,t1,t2)) = n + sum(t1) + sum(t2)
4
5
76
3
21
28
Example: Evaluating Expressions
● Define datatype of expressionsdata Exp = Var Int | Const Int | Plus (Exp, Exp)
● write (x+3)+ y as Plus(Plus(Var 1, Const 3), Var 2)● Evaluation function
ev :: Exp → Expev(Var n) = Var nev(Const n ) = Const nev(Plus(e1,e2)) = …
● Examplesev(Plus(Const 3, Const 2)) // Const 5ev(Plus(Var 1, Plus(Const 2, Const 3))) // Plus(Var 1, Const 5)
29
Case Expression
● Datatypedata Exp = Var Int | Const Int | Plus (Exp, Exp)
● Case expressioncase e of Var n -> ... Const n -> ... Plus(e1,e2) -> …
● Indentation matters in case statements in Haskell.
In ghci,
case e of {
Var n -> … ;
Const n -> … ;
Plus(e1,e2) -> … }
30
Evaluation by Cases
data Exp = Var Int | Const Int | Plus (Exp, Exp)let { ev ( Var n) = Var n; ev ( Const n ) = Const n; ev ( Plus ( e1,e2 ) ) = case ev e1 of { Var n -> Plus( Var n, ev e2) ; Const n -> case ev e2 of { Var m -> Plus( Const n, Var m); Const m -> Const (n+m); Plus(e3,e4) -> Plus ( Const n, Plus ( e3, e4 )) }; Plus(e3, e4) -> Plus( Plus ( e3, e4 ), ev e2) }}
31
Laziness
● Haskell is a lazy language● Functions and data constructors don’t evaluate
their arguments until they need themcond :: Bool -> a -> a -> acond True t e = tcond False t e = e
● Programmers can write control-flow operators that have to be built-in in eager languages
(||) :: Bool -> Bool -> Bool -- short-circuiting “or”True || x = TrueFalse || x = x
32
Lazy Evaluation
● An examplemagic :: Int -> Int -> [Int]magic 0 _ = [ ]magic m n = m : (magic n (m+n))getIt :: [Int] -> Int -> IntgetIt [ ] _ = 0getIt (x:xs) 1 = xgetIt (x:xs) n = getIt xs (n-1)
– getIt ( magic 1 1) 3● (magic 1 1) is just the fibonacci
numbers● the evaluation of (magic 1 1) never
terminates, but the evaluation of thisexpression in fact does
getIt ( magic 1 1 ) 3
=> getIt ( 1: (magic 1 (1+1)) ) 3
=> getIt ( magic 1 (1+1) ) (3-1)
=> getIt ( 1:(magic (1+1) (1+(1+1))))
(3-1)
=> getIt ( 1:(magic (1+1) (1+(1+1))))
2
=> getIt (magic (1+1) (1+(1+1)))
(2-1)
=> getIt ( magic 2 (1+(1+1))) (2-1)
=> getIt ( 2:(magic (1+(1+1))
(2+(1+(1+1)))) (2-1)
=> getIt ( 2:(magic (1+(1+1))
(2+(1+(1+1)))) 1
=> 2
33
Core Haskell
● Basic Types– Unit– Booleans– Integers– Strings– Reals– Tuples– Lists– Records
● Patterns● Declarations● Functions● Polymorphism● Type declarations● Type Classes● Monads● Exceptions
34
Testing
● It’s good to write tests as you write code● E.g. reverse undoes itself, etc.
reverse xs = let rev ( [ ], z ) = z rev ( y:ys, z ) = rev( ys, y:z ) in rev( xs, [ ] )--Write properties in Haskelltype TS = [Int]-- Test at this typeprop_RevRev :: TS -> Boolprop_RevRev ls = reverse (reverse ls) == ls
35
Test Interactively
Prelude> :m +Test.QuickCheckPrelude Test.QuickCheck>quickCheck prop_RevRev
● Test.QuickCheck is simply a Haskell library (not a “tool”)
Prelude Test.QuickCheck>:t quickCheckquickCheck :: Testable prop => prop -> IO ()
● IO: indicates that the function is impure (has side effects)
http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck
36
Things to Notice
● No side effects at all.reverse :: [a] → [a]
● A call to reverse returns a new list; the old one is unaffected.
prop_RevRev ls = reverse (reverse ls) == ls● A variable ls stands for an immutable value, not for
a location whose value can change● Laziness forces this purity
– Lazy evaluation makes it hard to reason about– Side effects in a lazy language would be extremely
unintuitive.
37
Things to Notice
● Purity makes the interface explicit.reverse :: [a] → [a] -- Haskell
– Takes a list, and returns a list; that's all.
void reverse ( list l ) /* C */– Takes a list, may modify it; may modify other persistent
state; may do I/O.
38
Things to Notice
Pure functions are easy to test.prop_RevRev ls = reverse (reverse ls) == ls
● In an imperative or OO language, you have to– set up the state of the object and the external state it
reads or writes– make the call– inspect the state of the object and the external state– perhaps copy part of the object or global state, so that
you can use it in the postcondition
39
Things to Notice
Types are everywhere.reverse :: [a] → [a]
● Usual static-typing panegyric omitted...● In Haskell, types express high-level design, in the
same way that UML diagrams do, with the advantage that the type signatures are machine-checked.
● Types are (almost always) optional: type inference fills them in if you leave them out.
HaskellYu Zhang
Acknowledgement: modified from Stanford CS242 https://courseware.stanford.edu/pg/courses/317431/
Course web site: http://staff.ustc.edu.cn/~yuzhang/fpl
Spring 2013
2
Reading
“Concepts in Programming Languages”Chapter 5https://courseware.stanford.edu/mod/file/download.php?file_guid=96710
“Real World Haskell”http://book.realworldhaskell.org/ https://rwh.readthedocs.org
Others● http://haskell.org/ghc/docs/latest/html/libraries/● Books&tutorials: http://haskell.org/haskellwiki/Books_and_tutorials● Research papers: http://haskell.org/haskellwiki/Research_papers ● Bloggers: http://haskell.org/haskellwiki/Blog_articles
AJAX 指异步 JavaScript 及 XML ( Asynchronous JavaScript And XML )。 AJAX 是一种在 2005 年由 Google 推广开来的编程模式。
3
Language Evolution
Algol 60
Algol 68
ML Modula
Lisp
Pascal
Haskell
C
C++
Smalltalk
Java
Many others: Algol 58, Algol W, Fortran, Ada, Perl, Python, Ruby, C#, Javascript, F#...
4
C Programming Language
● Dennis Ritchie, ACM Turing Award for Unix● Statically typed, general purpose systems programming
language● Computational model reflects underlying machine● Relationship between arrays and pointers
– An array is treated as a pointer to first element– E1[E2] is equivalent to ptr dereference: *((E1)+(E2))– Pointer arithmetic is not common in other languages
● Not statically type safe– If variable has type float, no guarantee value is floating pt
● Ritchie quote– “C is quirky, flawed, and a tremendous success”
5
ML programming language● Statically typed, general-purpose programming language
– “Meta-Language” of the LCF theorem proving system● Type safe, with formal semantics● Compiled language, but intended for interactive use● Combination of Lisp and Algol-like features
– Expression-oriented– Higher-order functions– Garbage collection– Abstract data types– Module system– Exceptions
● Used in printed textbook as example language
Robin Milner, ACM Turing-Award for ML, LCF Theorem Prover, ...
● LCF : Logic for Computable Functions
6
Haskell
● Haskell programming language is– Similar to ML: general-purpose, strongly typed, higher-order,
functional, supports type inference, interactive and compiled use– Different from ML: lazy evaluation, purely functional
core, rapidly evolving type system● Designed by committee in 80’s and 90’s to unify
research efforts in lazy languages– Haskell 1.0 in 1990, Haskell ‘98, Haskell’ ongoing– “A History of Haskell: Being Lazy with Class” HOPL 3
Paul Hudak
John Hughes
SimonPeyton Jones
Philip Wadler
Hudak, Paul; Hughes, John; Peyton Jones, Simon; Wadler, Philip (2007). "A History of Haskell: Being Lazy with Class". Proceedings of the third ACM SIGPLAN conference on History of programming languages (HOPL III): 12-1–55.
7
Haskell B Curry
● Combinatory logic– Influenced by Russell and Whitehead– Developed combinators to represent
substitution– Alternate form of lambda calculus that
has been used in implementation structures
● Type inference– Devised by Curry and Feys– Extended by Hindley, Milner
Although “Currying” and “Curried functions” are named after Curry, the idea was invented by Schoenfinkel earlier
8
Why Study Haskell?
● Good vehicle for studying language concepts● Types and type checking
– General issues in static and dynamic typing– Type inference– Parametric polymorphism– Ad hoc polymorphism (aka, overloading)
● Control– Lazy vs. eager evaluation– Tail recursion and continuations– Precise management of effects
9
Why Study Haskell?
● Functional programming will make you thinkdifferently about programming.– Mainstream languages are all about state– Functional programming is all about values
● Haskell is “cutting edge”– A lot of current research is done using Haskell– Rise of multi-core, parallel programming likely to make
minimizing state much more important● New ideas can help make you a better
programmer, in any language
cutting edge :最前沿
10
Most Research Languages
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The quick death
Geeks
Pra
ctit
ioners
11
Successful Research Languages
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The slow death
Geeks
Pra
ctit
ioners
12
C++, Java, Perl, Ruby
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000 The complete absence of death
Geeks
Pra
ctit
ioners Threshold of immortality
13
Haskell
1yr 5yr 10yr 15yr
1,000,000
1
100
10,000
The second life?
Geeks
Pra
ctit
ioners
“Learning Haskell is a great way of training yourself to think
functionally so you are ready to take full advantage of C# 3.0
when it comes out” (blog Apr 2007)
“I'm already looking at coding problems and my
mental perspective is now shifting back and forth between purely OO and
more FP styled solutions” (blog Mar 2007)
14
Haskell Implementation
● The Haskell Platform for Windows, Mac OS, Linux– First get and install Glasgow Haskell Compiler 7.4.2
http://www.haskell.org/ghc/ ./configure && sudo make install
– Install OpenGL utility toolkitsudo apt-get install freeglut3 freeglut3-dev
– Install the Haskell Platform 2012.4.0.0http://www.haskell.org/platform
./configure && make && sudo make install– Interactive
ghci or ghci intro.hs– Compiled
ghc -make intro.hs ./intro
15
Function Types in Haskell
● In Haskell, f :: A → B means for every x ∈ A,
f(x) = some element y = f(x) ∈ B
run forever
In words, “if f(x) terminates, then f(x) ∈ B.”
● In ML, functions with type A → B can throw an exception or have other effects, but not in Haskell
16
Higher-Order Functions● Functions that take other functions as arguments or return
as a result are higher-order functions.● Common Examples:
– Map: applies argument function to each element in a collection.– Reduce: takes a collection, an initial value, and a function, and
combines the elements in the collection according to the function.
● Google uses Map/Reduce to parallelize and distribute massive data processing tasks. (Dean & Ghemawat, OSDI 2004)
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl, applied to a binary operator, a starting value (typically the left-identity of the operator), and a list, reduces the list using the binary operator, from left to right
17
Basic Overview of Haskell
● Interactive Interpreter (ghci): read-eval-print– ghci infers type before compiling or executing
Type system does not allow casts or other loopholes!● Examples
Prelude> :set +t // print type after evaluationPrelude>(5+3)-26it :: IntegerPrelude> if 5>3 then “Harry” else “Hermione”“Harry”it :: [Char] -- String is equivalent to [Char]Prelude> 5==4Falseit :: Bool
● Prelude>:set +m // allow multiline commands● Prelude>:help
18
Overview by Type
● BooleansTrue, False :: Boolif ... then ... else … --types must match
● Integers0, 1, 2, ... :: Integer+, * , ...:: Integer-> Integer -> Integer
● Strings“Ron Weasley” :: [Char]
● String is a synonym for the type [Char]● Floats
1.0, 2.0, 3.14159, …:: Double
http://haskell.org/ghc/docs/latest/html/libraries/
19
Simple Compound Types
● Tuples(4, 5, “Griffendor”) :: (Integer, Integer, String)
● Lists[ ] :: [a] -- polymorphic type1 : [2, 3, 4] :: [Integer] -- infix cons notation
● Recordsdata Person = Person {firstName :: String, lastName :: String}
deriving (Eq, Ord, Show, Read)let hg = Person { firstName = “Hermione”, lastName = “Granger”}hg::Person
20
Patterns and Declarations
● Patterns can be used in place of variables<pat> ::= <var> | <tuple> | <cons> | <record> ...
● Value declarations– General form: <pat> = <exp>
let <pat> = <exp> // in ghci● ghci only accepts a highly restricted subset of Haskell
– ExamplesmyTuple = (“Flitwick”, “Snape”)(x,y) = myTuplemyList = [1, 2, 3, 4]z:zs = myList
– Local declarationslet (x,y) = (2, “Snape”) in x * 4
In ghci, you need input:● Prelude> let myTuple = …● Prelude> let (x,y) = …
Or you can save the left code into a file, e.g. ex.hs, then in ghci, you can input:● Prelude> :load ex.hs● Prelude>myTuple
21
Functions and Pattern Matching● Anonymous function
\x -> x+1 --like Lisp lambda, function (...) in JS● Function declaration form
<fname> <pat1> = <exp1>...<fname> <patn> = <expn> // default form in the slides
– In ghci,let { <fname> <pat> = <exp>;...; <fname> <pat> = <exp>}
● Examplesf (x,y) = x+y --argument must match pattern (x,y)length [ ] = 0length (x:s) = 1 + length(s)f :: Num a => (a, a) → a length :: Num a => [t] → a
22
Map Function on Lists
● Apply function to every element of listmap f [ ] = [ ]map f (x:xs) = f x : map f xs
– map :: (t → a) → [t] → [a]map (\x -> x+1) [1,2,3] // [2,3,4]
● Compare to Lisp(define map (lambda (f xs) (if (eq? xs ()) () (cons (f (car xs)) ((map f (cdr xs))))))
24
More Efficient Reverse
reverse xs = let rev ( [ ], accum ) = accum rev ( y:ys, accum ) = rev ( ys, y:accum ) in rev ( xs, [ ] )
1
2
3 1
2
3 1
2
3 1
2
3
25
List Comprehensions
● Notation for constructing new lists from old:myData = [1,2,3,4,5,6,7]twiceData = [2 * x | x <- myData] -- [2,4,6,8,10,12,14]twiceEvenData = [2 * x| x <- myData, x `mod` 2 == 0]
-- [4,8,12]● Similar to “set comprehension”
{ x | x ∈ Odd ∧ x > 6 }
26
Datatype Declarations
● Examplesdata Color = Red | Yellow | Blue
● elements are Red, Yellow, Blue
data Atom = Atom String | Number Int● elements are Atom “A”, Atom “B”, ..., Number 0, ...
data List = Nil | Cons (Atom, List)● elements are Nil, Cons(Atom “A”, Nil), ...● Cons(Number 2, Cons(Atom(“Bill”), Nil)), ...
● General formdata <name> = <clause> | ... | <clause><clause> ::= <constructor> | <contructor> <type>
● Type name and constructors must be Capitalized.
27
Datatypes and Pattern Matching
● Recursively defined data structuredata Tree = Leaf Int | Node (Int, Tree, Tree) deriving (Eq, Show, Read)Node(4, Node(3, Leaf 1, Leaf 2), Node(5, Leaf 6, Leaf 7))
● Recursive functionsum::Tree → Int sum (Leaf n) = nsum (Node(n,t1,t2)) = n + sum(t1) + sum(t2)
4
5
76
3
21
28
Example: Evaluating Expressions
● Define datatype of expressionsdata Exp = Var Int | Const Int | Plus (Exp, Exp)
● write (x+3)+ y as Plus(Plus(Var 1, Const 3), Var 2)● Evaluation function
ev :: Exp → Expev(Var n) = Var nev(Const n ) = Const nev(Plus(e1,e2)) = …
● Examplesev(Plus(Const 3, Const 2)) // Const 5ev(Plus(Var 1, Plus(Const 2, Const 3))) // Plus(Var 1, Const 5)
29
Case Expression
● Datatypedata Exp = Var Int | Const Int | Plus (Exp, Exp)
● Case expressioncase e of Var n -> ... Const n -> ... Plus(e1,e2) -> …
● Indentation matters in case statements in Haskell.
In ghci,
case e of {
Var n -> … ;
Const n -> … ;
Plus(e1,e2) -> … }
30
Evaluation by Cases
data Exp = Var Int | Const Int | Plus (Exp, Exp)let { ev ( Var n) = Var n; ev ( Const n ) = Const n; ev ( Plus ( e1,e2 ) ) = case ev e1 of { Var n -> Plus( Var n, ev e2) ; Const n -> case ev e2 of { Var m -> Plus( Const n, Var m); Const m -> Const (n+m); Plus(e3,e4) -> Plus ( Const n, Plus ( e3, e4 )) }; Plus(e3, e4) -> Plus( Plus ( e3, e4 ), ev e2) }}
31
Laziness
● Haskell is a lazy language● Functions and data constructors don’t evaluate
their arguments until they need themcond :: Bool -> a -> a -> acond True t e = tcond False t e = e
● Programmers can write control-flow operators that have to be built-in in eager languages
(||) :: Bool -> Bool -> Bool -- short-circuiting “or”True || x = TrueFalse || x = x
32
Lazy Evaluation
● An examplemagic :: Int -> Int -> [Int]magic 0 _ = [ ]magic m n = m : (magic n (m+n))getIt :: [Int] -> Int -> IntgetIt [ ] _ = 0getIt (x:xs) 1 = xgetIt (x:xs) n = getIt xs (n-1)
– getIt ( magic 1 1) 3● (magic 1 1) is just the fibonacci
numbers● the evaluation of (magic 1 1) never
terminates, but the evaluation of thisexpression in fact does
getIt ( magic 1 1 ) 3
=> getIt ( 1: (magic 1 (1+1)) ) 3
=> getIt ( magic 1 (1+1) ) (3-1)
=> getIt ( 1:(magic (1+1) (1+(1+1))))
(3-1)
=> getIt ( 1:(magic (1+1) (1+(1+1))))
2
=> getIt (magic (1+1) (1+(1+1)))
(2-1)
=> getIt ( magic 2 (1+(1+1))) (2-1)
=> getIt ( 2:(magic (1+(1+1))
(2+(1+(1+1)))) (2-1)
=> getIt ( 2:(magic (1+(1+1))
(2+(1+(1+1)))) 1
=> 2
33
Core Haskell
● Basic Types– Unit– Booleans– Integers– Strings– Reals– Tuples– Lists– Records
● Patterns● Declarations● Functions● Polymorphism● Type declarations● Type Classes● Monads● Exceptions
34
Testing
● It’s good to write tests as you write code● E.g. reverse undoes itself, etc.
reverse xs = let rev ( [ ], z ) = z rev ( y:ys, z ) = rev( ys, y:z ) in rev( xs, [ ] )--Write properties in Haskelltype TS = [Int]-- Test at this typeprop_RevRev :: TS -> Boolprop_RevRev ls = reverse (reverse ls) == ls
35
Test Interactively
Prelude> :m +Test.QuickCheckPrelude Test.QuickCheck>quickCheck prop_RevRev
● Test.QuickCheck is simply a Haskell library (not a “tool”)
Prelude Test.QuickCheck>:t quickCheckquickCheck :: Testable prop => prop -> IO ()
● IO: indicates that the function is impure (has side effects)
http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck
36
Things to Notice
● No side effects at all.reverse :: [a] → [a]
● A call to reverse returns a new list; the old one is unaffected.
prop_RevRev ls = reverse (reverse ls) == ls● A variable ls stands for an immutable value, not for
a location whose value can change● Laziness forces this purity
– Lazy evaluation makes it hard to reason about– Side effects in a lazy language would be extremely
unintuitive.
lazy evaluation makes it hard to reason about when things will be evaluated; hence including side effects in a lazy language would be extremely unintuitive. Historically, this is the reason Haskell is pure: initially, the designers of Haskell wanted to make a lazy functional language, and quickly realized it would be impossible unless it also disallowed side effects.
http://www.cis.upenn.edu/~cis194/lectures/2012-02-16.html
37
Things to Notice
● Purity makes the interface explicit.reverse :: [a] → [a] -- Haskell
– Takes a list, and returns a list; that's all.
void reverse ( list l ) /* C */– Takes a list, may modify it; may modify other persistent
state; may do I/O.
38
Things to Notice
Pure functions are easy to test.prop_RevRev ls = reverse (reverse ls) == ls
● In an imperative or OO language, you have to– set up the state of the object and the external state it
reads or writes– make the call– inspect the state of the object and the external state– perhaps copy part of the object or global state, so that
you can use it in the postcondition
39
Things to Notice
Types are everywhere.reverse :: [a] → [a]
● Usual static-typing panegyric omitted...● In Haskell, types express high-level design, in the
same way that UML diagrams do, with the advantage that the type signatures are machine-checked.
● Types are (almost always) optional: type inference fills them in if you leave them out.