a lightning tour of haskell

80
A Lightning Tour of Haskell Lecture 1, Designing and Using Combinators John Hughes

Upload: vahe

Post on 25-Feb-2016

44 views

Category:

Documents


0 download

DESCRIPTION

A Lightning Tour of Haskell. Lecture 1, Designing and Using Combinators John Hughes. Using Haskell: The Hugs Interpreter. Using Haskell: The Hugs Interpreter. A module is loaded. Using Haskell: The Hugs Interpreter. A module is loaded. Type an expression at the prompt. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: A Lightning Tour of Haskell

A Lightning Tour of Haskell

Lecture 1,Designing and Using Combinators

John Hughes

Page 2: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

Page 3: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

A module isloaded.

Page 4: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

A module isloaded.

Type anexpression atthe prompt.

Page 5: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

A module isloaded.

Type anexpression atthe prompt.The value

is printed.

Page 6: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

A functioncall with twoarguments.

No brackets!

Brackets areonly for grouping

e.g. f (g x)

Page 7: A Lightning Tour of Haskell

Using Haskell: The Hugs Interpreter

A linked list

1

3

5

1 : 3 : 5 : []

Page 8: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Page 9: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Page 10: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Ignore for now

Page 11: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Ignore for now Type of firstargument: “a”

Page 12: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Ignore for now Type of firstargument: “a”

Type of secondargument:list of “a”s

Page 13: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Ignore for now Type of firstargument: “a”

Type of secondargument:list of “a”s

Type ofresult

Page 14: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Type signature.Optional!

Ignore for now Type of firstargument: “a”

Type of secondargument:list of “a”s

Type ofresult

What is “a”? A type variable which can stand for any type.

This function is polymorphic.

Page 15: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Definition by “patternmatching”: case

analysis on the formof the arguments.

Page 16: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Definition by “patternmatching”: case

analysis on the formof the arguments.

“Guards” defineconditions for anequation to apply.

Page 17: A Lightning Tour of Haskell

Defining Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

Definition by “patternmatching”: case

analysis on the formof the arguments.

“Guards” defineconditions for anequation to apply.

We build anew structureas the result:

“purelyfunctional”.

Page 18: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Page 19: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Type name

Page 20: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Type name Type parameter

•Types may take parameters.

•Enables us to define polymorphic functions which work on a tree with any type of labels.

Page 21: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Type name Type parameter

•Types may take parameters.

•Enables us to define polymorphic functions which work on a tree with any type of labels.

Constants startwith upper case,

variables with lower

Page 22: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Node and Leaf arealternative forms of Tree.

Page 23: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Node and Leaf arealternative forms of Tree.

Types of thecomponents.

Page 24: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Node and Leaf arealternative forms of Tree.

Types of thecomponents.

Ignore for now.

Page 25: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Page 26: A Lightning Tour of Haskell

Defining Data Types

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Type:Tree Integer

Page 27: A Lightning Tour of Haskell

Tree Insertion

insertTree :: Ord a => a -> Tree a -> Tree ainsertTree x Leaf = Node x Leaf LeafinsertTree x (Node y l r) | x < y = Node y (insertTree x l) r | x > y = Node y l (insertTree x r) | x==y = Node y l r

Patternmatchingworks asfor lists.

Page 28: A Lightning Tour of Haskell

Overloading•Polymorphic functions use the same definition at each type.

•Overloaded functions may have a different definition at each type.

class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x/=y = not (x==y)

Class name.

Classmethods

and types.

Default definition.

Read:

“a is a type in class Eq, if it has the following methods”.

Page 29: A Lightning Tour of Haskell

The Class Hierarchy

class Eq a => Ord a where (<) :: a -> a -> Bool …

Read:

“Type a in class Eq is also in class Ord, if it provides the following methods…”

Page 30: A Lightning Tour of Haskell

Instance Declarations

instance Eq Integer where x==y = …primitive…

instance Eq a => Eq [a] where [] == [] = True x:xs == y:ys =

x == y && xs == ys

Provided a is in class Eq, then [a] is in class Eq, with the method definition given.

Page 31: A Lightning Tour of Haskell

Types of Overloaded Functions

insert :: Ord a => a -> [a] -> [a]insert x [] = []insert x (y:xs) | x<=y = x:y:xs

| x>y = y:insert x xs

“a” may be any typein class Ord.

Because insertuses a method

from class Ord.

Page 32: A Lightning Tour of Haskell

Show and Read

class Show a where show :: a -> String

class Read a where read :: String -> a

These are simplifications: there are more methods in reality.

read . show = id (usually)

Page 33: A Lightning Tour of Haskell

Derived Instances

data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

Constructs a “defaultinstance” of class Show.

Main> show (Node 1 Leaf (Node 2 Leaf Leaf))"Node 1 Leaf (Node 2 Leaf Leaf)"

Works for many standard classes.

Page 34: A Lightning Tour of Haskell

Multi-Parameter Classes

Define relations between classes.

class Collection c a where empty :: c add :: a -> c -> c member :: a -> c -> Bool

c is a collection with elements of type a.

instance Eq a => Collection [a] a where empty = [] add = (:) member = elem

instance Ord a => Collection (Tree a) a where empty = Leaf add = insertTree member = elemTree

Page 35: A Lightning Tour of Haskell

Functional Dependencies

class Collection c a | c -> a where empty :: c add :: a -> c -> c member :: a -> c -> Bool

A functional dependency

•Declares that c determines a: there can be only one instance for each type c.

•Helps the type-checker resolve ambiguities (tremendously).add x (add y empty) -- x and y must be the same type.

Page 36: A Lightning Tour of Haskell

“Side Effects” in HaskellSuppose

tick :: String -> Integer

•reads an integer n from a file with given name,

•writes n+1 back to the file

•returns n

Then tick == tick might be False!

Cannot replace equals by equals.

Not “purely functional”!

Page 37: A Lightning Tour of Haskell

Haskell’s SolutionSide effects are recorded in the type!

readFile :: String -> IO StringwriteFile :: String -> String -> IO ()

So the type of tick is

tick :: String -> IO Int

and tick == tick is ill-typed.

Performs I/Oand delivers

a String.

IO is a monad --more later!

Page 38: A Lightning Tour of Haskell

The do notation

I/O actions may be combined in sequence.

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Page 39: A Lightning Tour of Haskell

The do notation

I/O actions may be combined in sequence.

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Type: IO String

Type: String Scope ofcontents

Page 40: A Lightning Tour of Haskell

The do notation

I/O actions may be combined in sequence.

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Localdeclaration

Scope

Page 41: A Lightning Tour of Haskell

The do notation

I/O actions may be combined in sequence.

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Type: IO ()

No need tobind a nameto the result.

Page 42: A Lightning Tour of Haskell

The do notation

I/O actions may be combined in sequence.

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Type: IO IntegerDefines result of tick.

return :: a -> IO a

Page 43: A Lightning Tour of Haskell

IO a = Action Yeilding an a

Page 44: A Lightning Tour of Haskell

IO a = Action Yeilding an a

Action at theprompt is performed.

The actionreturned by tickhas a side-effect.

Yields a differentInteger each timeit is performed.

Page 45: A Lightning Tour of Haskell

IO a = Action Yeilding an a

twice1 :: IO a -> (IO a, IO a)twice1 c = (c,c)

Result is not an action!Therefore not performed.

Next call reveals noside-effects occurred.

Page 46: A Lightning Tour of Haskell

IO a = Action Yeilding an atwice2 :: IO a -> IO (a,a)twice2 a = do x <- a

return (x,x)

twice3 :: IO a -> IO (a,a)twice3 a = do x <- a

y <- areturn (x,y)

The same action can beperformed many times.

Page 47: A Lightning Tour of Haskell

ReferencesVariables in Haskell cannot be updated -- references can.

newIORef :: a -> IO (IORef a)readIORef :: IORef a -> IO awriteIORef :: IORef a -> a -> IO ()

Reference operations have side-effects -- hence IO type.

Page 48: A Lightning Tour of Haskell

Example: Destructive List Insertion

data RList a = Nil | Cons a (IORef (RList a))

insertRList :: Ord a => a -> IORef (RList a) -> IO ()insertRList x xs = do cell <- readIORef xs case cell of

Nil -> do new <- newIORef Nil writeIORef xs (Cons x new) Cons y xs' | x<=y -> do new <- newIORef cell

writeIORef xs (Cons x new) | x>y -> insertRList x xs'

Updateabletail.

Must read the list cell.

case isinlinepattern

matching.

Create newcell and

update old.

Page 49: A Lightning Tour of Haskell

Encapsulated Side Effects

•IORefs can only be updated at the top level.

•Can we use references internally to define a pure function?

Example

removeDuplicates :: Hashable a => [a] -> [a]

Use a hash tableinternally to makecomparison fast.

No IO type:no externally

visible side-effects!

Array operationsresemble reference ones.

Page 50: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

Similar family of operations.

Page 51: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

s ties together the typeof a reference and theaction which uses it.

Page 52: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

The encapsulation function:

runST :: (forall s . ST s a) -> a

Page 53: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

The encapsulation function:

runST :: (forall s . ST s a) -> a

Result typefree from ST:

“pure”.

Page 54: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

The encapsulation function:

runST :: (forall s . ST s a) -> a

Result typefree from ST:

“pure”.

Each use binds a freshvariable s: labels references

created, guarantees usedonly here.

Page 55: A Lightning Tour of Haskell

Encapsulation: The ST Monad

newSTRef :: a -> ST s (STRef s a)readSTRef :: STRef s a -> ST s awriteSTRef :: STRef s a -> a -> ST s ()

The encapsulation function:

runST :: (forall s . ST s a) -> a

The argument of runSTmust be polymorphic in s.

This is a “rank 2” type.Cannot be inferred --

must be declared.

Page 56: A Lightning Tour of Haskell

Overloading Side-Effects

Why should we choose between IO and ST when we want side-effects?

class Monad m => RefMonad m r | m -> r where newRef :: a -> m (r a) readRef :: r a -> m a writeRef :: r a -> a -> m ()

instance RefMonad IO IORef …

instance RefMonad (ST s) (STRef s) …

Page 57: A Lightning Tour of Haskell

Overloading Side-Effects

Why should we choose between IO and ST when we want side-effects?

class Monad m => RefMonad m r | m -> r where newRef :: a -> m (r a) readRef :: r a -> m a writeRef :: r a -> a -> m ()

instance RefMonad IO IORef …

instance RefMonad (ST s) (STRef s) …

Partial type application.Plug in ST s and STRef s for m and r in the types…

Page 58: A Lightning Tour of Haskell

Overloading Side-Effects

Why should we choose between IO and ST when we want side-effects?

class Monad m => RefMonad m r | m -> r where newRef :: a -> ST s (STRef s a) readRef :: STRef s a -> ST s a writeRef :: STRef s a -> a -> ST s ()

instance RefMonad IO IORef …

instance RefMonad (ST s) (STRef s) …

Page 59: A Lightning Tour of Haskell

Overloading Side-Effects

Why should we choose between IO and ST when we want side-effects?

class Monad m => RefMonad m r | m -> r where newRef :: a -> m (r a) readRef :: r a -> m a writeRef :: r a -> a -> m ()

Example

data RList r a = Nil | Cons a (r (RList r a))insertRList :: (Ord a, RefMonad m r) =>

a -> r (RList r a) -> m ()

Page 60: A Lightning Tour of Haskell

Higher-Order Functions•Functions are values in Haskell.

•“Program skeletons” take functions as parameters.

takeWhile :: (a -> Bool) -> [a] -> [a]takeWhile p [] = []takeWhile p (x:xs) | p x = x:takeWhile p xs | otherwise = []

Takes a prefix of a list, satisfying a predicate.

Page 61: A Lightning Tour of Haskell

Denoting Functions

Page 62: A Lightning Tour of Haskell

Denoting Functions

below a b = b < a

Page 63: A Lightning Tour of Haskell

Denoting Functions

below a b = b < a

takeWhile :: (a -> Bool) -> [a] -> [a]takeWhile p [] = []takeWhile p (x:xs) | p x = x:takeWhile p xs | otherwise = []

Page 64: A Lightning Tour of Haskell

Denoting Functions

below a b = b < a

takeWhile :: (a -> Bool) -> [a] -> [a]takeWhile p [] = []takeWhile p (x:xs) | below 10 x= x:takeWhile p xs | otherwise = []

A partial function application.

Page 65: A Lightning Tour of Haskell

More Ways to Denote Functions

•takeWhile (below 10) [1,5,9,15,20] below a b = b < a

Page 66: A Lightning Tour of Haskell

More Ways to Denote Functions

•takeWhile (below 10) [1,5,9,15,20]

•takeWhile (\b -> b < 10) [1,5,9,15,20]

below a b = b < a

“Lambda” expression.Function definition

in place.

Page 67: A Lightning Tour of Haskell

More Ways to Denote Functions

•takeWhile (below 10) [1,5,9,15,20]

•takeWhile (\b -> b < 10) [1,5,9,15,20]

below a b = b < a

“Lambda” expression.Function definition

in place.f b = b < 10

Page 68: A Lightning Tour of Haskell

More Ways to Denote Functions

•takeWhile (below 10) [1,5,9,15,20]

•takeWhile (\b -> b < 10) [1,5,9,15,20]

•takeWhile (<10) [1,5,9,15,20]

below a b = b < a

“Lambda” expression.Function definition

in place.f b = b < 10

Partial operatorapplication -- argument

replaces missing operand.

Page 69: A Lightning Tour of Haskell

Lazy Evaluation

•Expressions are evaluated only when their value is really needed!

•Function arguments, data structure components, are held unevaluated until their value is used.

from n = n : from (n+1)

Page 70: A Lightning Tour of Haskell

Lazy Recursive Definitions

nats = 0 : map (+1) nats

Page 71: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

Page 72: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

The file is onlyopened here, itis read when

contents is needed.

Page 73: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

The file is onlyopened here, itis read when

contents is needed.

Not needed yet!n isn’t needed…

Page 74: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

The file is onlyopened here, itis read when

contents is needed.

Not needed yet!n isn’t needed…

Not needed untilafter the file is

opened for writing!

Page 75: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentswriteFile f (show (n+1))return n

The file is onlyopened here, itis read when

contents is needed.

Not needed yet!n isn’t needed…

Not needed untilafter the file is

opened for writing!So readFile sees an empty file!

Page 76: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contentsn `seq` writeFile f (show (n+1))return n

Page 77: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contents n `seq` writeFile f (show (n+1))return n

`seq` evaluatesits first argument,

then returns itssecond.

Page 78: A Lightning Tour of Haskell

A ConfessionThis program doesn’t work!

tick :: String -> IO Integertick f = do contents <- readFile f

let n = read contents n `seq` writeFile f (show (n+1))return n

`seq` evaluatesits first argument,

then returns itssecond.

Backquotes `…`turn a functionname into an

operator.

Page 79: A Lightning Tour of Haskell

Time for a Demo…

Page 80: A Lightning Tour of Haskell

Course Home Page

www.cs.chalmers.se/~rjmh/Combinators

Begin with some “finger exercises” in Haskell.