A Taste of Function Programming Using Haskell PDF
A Taste of Function Programming Using Haskell PDF
DRAFT D. Vermeir
1 / 60
Introduction
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
2 / 60
4 5
Introduction
What is Haskell?
Haskell is a lazy pure functional programming language. functional because the evaluation of a program is equivalent to evaluating a function in the pure mathematical sense; also there are no variables, objects, .. Other functional languagues include Lisp, Scheme, Erlang, Clean, ML, OCaml, . . . pure because it does not allow side effects (that affect the state of the world). One benet is referential transparency. This makes Haskell also a declarative language. lazy (aka non-strict) because expressions that are not needed for the result are not evaluated. This allows e.g. to support innite datastructures.
3 / 60
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
4 / 60
4 5
Precedence
f g 5
= ((f g) 5)
Inx operators can be (left/right/non) associative and have a precedence between 0 (low) and 9 (high).
prec 9 8 7 6 5 4 3 2 1 0 left !! *, /, div, rem, quot +, mod, non . ^, ^^, ** right
:, ++ ==, /=, <, <=, >, >=, elem, notElem && || >>=, >> $, $!, seq
5 / 60
e.g. 1/0
6 / 60
type (expression)
Integer Char [Integer] (Char,Integer) Integer -> Integer
7 / 60
Declarations
8 / 60
Polymorphic Types
Polymorphic type expressions are universally quantied over types. They describe families of types. [] describes all types of the form list of for some type .
length
length :: [a] -> Integer length [] = 0 -- pattern matching on argument length (x:xs) = 1 + length xs -- : is cons
Example usage:
length [1,2,3] -- 3 length [a,b,c] -- 3 length [[1],[2],[3]] -- 3
9 / 60
head :: [a] -> a head (x:xs) = x -- error if no match, e.g. for empty list tail :: [a] -> [a] tail (x:xs) = xs
10 / 60
Type Hierarchy
A value may have several types, e.g. [a,b]::[Char] and [a,b]::[a]. Every well-typed expression is guaranteed to have a unique principal type, i.e. the least general type that, intuitively, contains all instances of the expression. For example, the principal type of head is [a]->a, although e.g. a and [b]->a are also types for head. The principal type of a well-typed expression can be inferred automatically. is shared by all types
11 / 60
The type Bool has exactly two values: True and False. Type Bool is an example of a (nullary) type constructor, and True and False are (also nullary) (data) constructors.
-- another sum (disjoint union) type data Color = Red | Green | Blue | Indigo | Violet
12 / 60
Note that Point is also polymorphic: Point t is a type for any type
t. Pt Pt Pt -2.0 3.0 :: Point Float a b :: Point Char True False :: Point Bool Pt 1 a is ill-typed
Since the namespaces for type constructors (Point) and data constructors (Pt) are separate, one can use the same name for both.
data Point a = Point a a
13 / 60
14 / 60
Type Synonyms
15 / 60
Built-in types
characters:
data Char = a | b | c | ... -- This is not valid | A | B | C | ... -- Haskell code! | 1 | 2 | 3 | ... ...
16 / 60
Built-in types
List Comprehension
17 / 60
Functions
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
18 / 60
4 5
Functions
Dening Functions
Example:
map :: (a->b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs -- precedence: (f x) : (map f xs) map (add 1) [1,2,3] -[2,3,4]
19 / 60
Functions
Dening Functions
Anonymous Functions
20 / 60
Functions
Dening Functions
21 / 60
Functions
Lazy Evaluation
An expression is not evaluated until it is needed (and then only the parts that are needed are evaluated).
22 / 60
Functions
Zip
zip (x:xs) (y:ys) = (x,y) : zip xs ys zip xs ys = []
Fibonacci Sequence
fib = 1 : 1 : [ a + b | (a,b) <- zip fib (tail fib) ] -- fib = 1 1 2 3 5 8 ..
23 / 60
Functions
Pattern Matching
Using constructors of any type, formal parameters or wild cards.
f :: ([a], Char, (Int, Float), String, Bool) -> Bool f ([], b, (1,2.0), "hi", _) = False -- last one is wild card f (_, _, (2,4.0), "", True) = True f (x, _, (2,4.0), "", y) = length x > 0 || y -- formal pars -- only 1 occurrence of same formal parameter in pattern
Semantics
if match succeeds: bind formal parameter fails: try next pattern diverges: (): return
24 / 60
Functions
-1 -- otherwise is True
25 / 60
Functions
take1, take2
take1 0 _ = [] take1 _ [] = [] take1 n (x:xs) = x : take1 (n-1) xs take2 _ [] = [] take2 0 _ = [] take2 n (x:xs) = x : take2 (n-1) xs
different results
take1 take2 take1 take2 0 bot -- [] 0 bot -- bot [] -- bot [] -- []
26 / 60
Functions
if .. then .. else
if (e1 ) then e2 else e3
is short for
case (e1 ) of True -> e2 False -> e3
27 / 60
Functions
is equivalent to
f x1 x2 .. xn = case (x1 x2 .. (p1,1 , .. , p1,n ) -> e1 (p2,1 , .. , p2,n ) -> e2 ... (pm,1 , .. , pm,n ) -> em xn ) of
28 / 60
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
29 / 60
4 5
Restricted Polymorphism
List Membership
-- x elem list iff x appears in list x elem [] = False x elem (y:ys) = x == y || ( x elem ys)
Type of elem
One would expect: elem:: a -> [a] -> Bool but this would imply (==):: a -> a -> Bool but == may not be dened on some types! Thus elem:: a -> [a] -> Bool only for a where (==):: a -> a -> Bool is dened.
30 / 60
Type Classes
Class Eq
-- A type a is an instance of the class Eq iff -- there is an appropriate overloaded operation == defined on it class Eq a where (==) :: a -> a -> Bool
31 / 60
Integer is an instance of Eq
instance Eq Integer where x == y = x integerEq y -- integerEq is primitive
32 / 60
33 / 60
Monads
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
34 / 60
4 5
Monads
Debuggable Functions
Example Problem
f,g :: Int -> Int
"g." x g f "f."
++
"g.f."
35 / 60
Monads
Debuggable Functions
A Complex Solution
s++t
s y
t z
++
Monads
Debuggable Functions
Introducing bind
Debug info for f.g
f,g :: Int -> (Int,String)
requirements
must accept output from g as input
bind f
and thus
bind :: ((Int -> (Int,String)) -> (Int,String) -> (Int,String)
37 / 60
Monads
Debuggable Functions
bind f s y t z ++ s++t
bind :: ((Int -> (Int,String)) -> (Int,String) -> (Int,String) bind f (gx,gs) = let (fx,fs) = f gx in (fx,gs++fs)
For 3 functions: bind h . bind f . g etc. We write g >>= f (low precedence) for bind f . g.
38 / 60
Monads
Debuggable Functions
Monads
Debuggable Functions
Theorem
unit >>= f
= f
Proof.
unit >>= f = bind f .unit = x bind f (unit x) = x bind f (x, ) = x ((u, v ) let (y , s) = f u in (y , v ++s))(x, ) = x ( let (y , s) = f x in (y , ++s)) = x ( let (y , s) = f x in (y , s)) = x f x = f
40 / 60
Monads
Debuggable Functions
Theorem
(f >>= unit)
= f
Proof.
f >>= unit = bind unit .f = x bind unit (f x) = x ((u, v ) let (y , s) = unit u in (y , v ++s))(f x) = x ((u, v ) let (y , s) = (u, ) in (y , v ++s))(f x) = x ((u, v ) (u, v ++))(f x) = x ((u, v ) (u, v ))(f x) = x f x = f
41 / 60
Monads
Debuggable Functions
Theorem
(lift g >>= lift f)
= lift (f.g)
Proof.
lift g >>= lift f = bind (lift f ).lift g = x bind (lift f )(lift g x) = x bind (unit.f )(unit.g x) = x bind (unit.f )(gx, ) = x ((u, v ) let (y , s) = unit.f u in (y , v ++s))(gx, ) = x let (y , s) = unit.f (gx) in (y , ++s) = x let (y , s) = (f (gx), ) in (y , s) = x (f .g x, ) = x unit.(f .g) x = unit.(f .g) = lift f .g
42 / 60
Monads
Stateful Functions
Stateful Functions
Another way of looking at such functions hides the part involving the state(s).
43 / 60
Monads
Stateful Functions
gThenF (g;f in C)
g :: a -> s -> (b, s) f :: b -> s -> (c, s) gThenF :: (a -> s -> (b,s)) -> (b -> s -> (c,s)) -> a -> s -> (c, s) gThenF g f a = \s -> let (gOut, s) = g a s in f gOut s
44 / 60
Monads
Stateful Functions
requirements
bind f . g
a s
bind bind -- g bind -- f bind
b s
c s
f . g a :: s -> (s, c) f . g :: a -> s -> (s,c) :: a -> ( s -> (b,s) ) f :: (s -> (b,s)) -> s -> (s,c) :: b -> ( s -> (c,s) ) :: (b -> ( s -> (c,s) )) -> ((s -> (b,s)) -> s -> (s,c))
45 / 60
Monads
Stateful Functions
Bind Implementation
bind f . g
a s
b s
c s
bind :: (b -> ( s -> (c,s) )) -> ((s -> (b,s)) -> s -> (s,c)) bind f ga = \s -> let (b, s) = ga s in f b s
46 / 60
Monads
Stateful Functions
bind :: (b -> ( s -> (c,s) )) -> ((s -> (b,s)) -> s -> (s,c)) bind f ga = \s -> let (b, s) = ga s in f b s
it works
bind f . g a = bind f ( g a) = \s -> let (b, s) = (g a) s in f b s
example
h :: c -> s -> (d,s) bind h . bind f . g a :: s -> (d,s) -- we write g >>= f for bind f . g (g >>= f >>= h) a s
47 / 60
Monads
Stateful Functions
Monads
Stateful Functions
unit.h a s
b s
b s
c s
g :: a -> s -> (b,s) h :: b -> b f :: b -> s -> (c,s) -- lift h :: b -> s -> (b,s) (g >> lift h >> f) a s
49 / 60
Monads
Monads
Monads
Monads
Monads
data M a = .. -- in general bind :: (a -> M b) -> (M a -> M b) unit :: a -> M a infixl 1 >>= -- infix, right-associative, prec. 1 (low) (>>=) :: M a -> (a -> M b) -> M b ma >>= f = bind f ma -- in our examples return :: a -> M a return = unit -- in our examples
where
return a >>= f ma >>= return ma >>= (\x -> f x >>= h)
= = =
51 / 60
Monads
Monads
= =
52 / 60
Monads
Maybe Monad
Code to avoid
e :: Maybe a f :: a -> Maybe a case e of Nothing -> Nothing Just x -> f x
53 / 60
Monads
Maybe Monad
Maybe Monad
instance Monad Maybe where Nothing >>= f = Nothing (Just x) >>= f = f x return = Just
Code to avoid
e :: Maybe a f :: a -> Maybe a case e of Nothing -> Nothing Just x -> f y
.. becomes
e >>= f -- will not call f unless ..
54 / 60
Monads
The IO Monad
IO a
A value x:: IO a represents an action that, when performed, does some I/O before delivering a value of type a
a
IO a
World World
55 / 60
Monads
The IO Monad
getChar, putChar
Read/write a single character.
getChar :: IO Char putChar :: Char -> IO () -- returns trivial value ()
IO bind
(>>=) :: IO a -> ( a -> IO b) -> IO b echo :: IO() echo = getChar >>= putChar -- a = Char, b = ()
Char World getChar::IO Char World putChar::IO () () World
echo :: IO ()
56 / 60
Monads
The IO Monad
echo; echo
(>>=) :: IO a -> ( a -> IO b) -> IO b -- echo :: IO () echo >>= echo -- ERROR: 2nd echo should be function () -> IO ()
(>>) :: IO a -> IO b -> IO b -- throw away result first argument (>>) a1 a2 = a1 >>= (\x -> a2) echo >> echo -- OK, read >> as then
return
return :: a -> IO a
a World
return a (return
World
a):: IO a
57 / 60
Monads
The IO Monad
get2Chars
get2Chars :: IO (Char, Char) get2Chars = getChar >>= \c1 -> (getChar >>= (\c2 -> return (c1,c2)))
58 / 60
Epilogue
1 2
Introduction Expressions, Values, Types User Dened Types Built-in types Functions Dening Functions Laziness and Innite Data Structures Case Expressions and Pattern Matching Type Classes and Overloading Monads Debuggable Functions Stateful Functions Monads Maybe Monad The IO Monad Epilogue
59 / 60
4 5
Epilogue
Not Covered
modules, named elds, arrays, nite maps, strict elds, kinds, comonads, arrows, monad transformers, parsing monads, type theory ...
References
See website. Most of the material on these slides comes from A Gentle Introduction to Haskell 98 by Hudak et al. The Monad introduction is based on http://sigfpe.blogspot.com/2006/08/ you-could-have-invented-monads-and.html S. Peyton Jones, Tackling the Awkward Squad: monadic I/O, concurrency, exception and foreign-language calls in Haskell, 2005.
Acknowledgements
Dries Harnie pointed out errors in earlier versions.
60 / 60