1 / 80

A Lightning Tour of Haskell

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.

vahe
Download Presentation

A Lightning Tour of Haskell

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Using Haskell: The Hugs Interpreter

  3. Using Haskell: The Hugs Interpreter A module is loaded.

  4. Using Haskell: The Hugs Interpreter A module is loaded. Type an expression at the prompt.

  5. Using Haskell: The Hugs Interpreter A module is loaded. Type an expression at the prompt. The value is printed.

  6. Using Haskell: The Hugs Interpreter A function call with two arguments. No brackets! Brackets are only for grouping e.g. f (g x)

  7. Using Haskell: The Hugs Interpreter A linked list 1 3 5 1 : 3 : 5 : []

  8. 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

  9. Defining Functions Type signature. Optional! insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs

  10. Defining Functions Type signature. Optional! Ignore for now insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs

  11. Defining Functions Type signature. Optional! Ignore for now Type of first argument: “a” insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs

  12. Defining Functions Type signature. Optional! Ignore for now Type of first argument: “a” insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs Type of second argument: list of “a”s

  13. Defining Functions Type signature. Optional! Ignore for now Type of first argument: “a” Type of result insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs Type of second argument: list of “a”s

  14. Defining Functions Type signature. Optional! Ignore for now Type of first argument: “a” Type of result insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs Type of second argument: list of “a”s What is “a”? A type variable which can stand for any type. This function is polymorphic.

  15. 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 “pattern matching”: case analysis on the form of the arguments.

  16. 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 “pattern matching”: case analysis on the form of the arguments. “Guards” define conditions for an equation to apply.

  17. Defining Functions We build a new structure as the result: “purely functional”. 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 “pattern matching”: case analysis on the form of the arguments. “Guards” define conditions for an equation to apply.

  18. Defining Data Types data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

  19. Defining Data Types Type name data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

  20. Defining Data Types Type name Type parameter data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show • Types may take parameters. • Enables us to define polymorphic functions which work on a tree with any type of labels.

  21. Defining Data Types Type name Type parameter data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show Constants start with upper case, variables with lower • Types may take parameters. • Enables us to define polymorphic functions which work on a tree with any type of labels.

  22. Defining Data Types Node and Leaf are alternative forms of Tree. data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

  23. Defining Data Types Node and Leaf are alternative forms of Tree. data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show Types of the components.

  24. Defining Data Types Node and Leaf are alternative forms of Tree. data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show Ignore for now. Types of the components.

  25. Defining Data Types data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show

  26. Defining Data Types data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show Type: Tree Integer

  27. Tree Insertion insertTree :: Ord a => a -> Tree a -> Tree a insertTree x Leaf = Node x Leaf Leaf insertTree 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 Pattern matching works as for lists.

  28. Overloading • Polymorphic functions use the same definition at each type. • Overloaded functions may have a different definition at each type. Class name. Read: “a is a type in class Eq, if it has the following methods”. class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x/=y = not (x==y) Class methods and types. Default definition.

  29. The Class Hierarchy Read: “Type a in class Eq is also in class Ord, if it provides the following methods…” class Eq a => Ord a where (<) :: a -> a -> Bool …

  30. 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.

  31. Types of Overloaded Functions “a” may be any type in class Ord. insert :: Ord a => a -> [a] -> [a] insert x [] = [] insert x (y:xs) | x<=y = x:y:xs | x>y = y:insert x xs Because insert uses a method from class Ord.

  32. 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)

  33. Derived Instances data Tree a = Node a (Tree a) (Tree a) | Leaf deriving Show Constructs a “default instance” of class Show. Works for many standard classes. Main> show (Node 1 Leaf (Node 2 Leaf Leaf)) "Node 1 Leaf (Node 2 Leaf Leaf)"

  34. 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

  35. Functional Dependencies A functional dependency class Collection c a | c -> a where empty :: c add :: a -> c -> c member :: a -> c -> Bool • 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.

  36. “Side Effects” in Haskell • Suppose • 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”!

  37. Haskell’s Solution Performs I/O and delivers a String. Side effects are recorded in the type! readFile :: String -> IO String writeFile :: String -> String -> IO () So the type of tick is tick :: String -> IO Int and tick == tick is ill-typed. IO is a monad -- more later!

  38. The do notation I/O actions may be combined in sequence. tick :: String -> IO Integer tick f = do contents <- readFile f let n = read contents writeFile f (show (n+1)) return n

  39. The do notation I/O actions may be combined in sequence. Type: IO String tick :: String -> IO Integer tick f = do contents <- readFile f let n = read contents writeFile f (show (n+1)) return n Type: String Scope of contents

  40. The do notation I/O actions may be combined in sequence. tick :: String -> IO Integer tick f = do contents <- readFile f let n = read contents writeFile f (show (n+1)) return n Local declaration Scope

  41. The do notation I/O actions may be combined in sequence. tick :: String -> IO Integer tick f = do contents <- readFile f let n = read contents writeFile f (show (n+1)) return n Type: IO () No need to bind a name to the result.

  42. The do notation I/O actions may be combined in sequence. tick :: String -> IO Integer tick f = do contents <- readFile f let n = read contents writeFile f (show (n+1)) return n Type: IO Integer Defines result of tick. return :: a -> IO a

  43. IO a = Action Yeilding an a

  44. IO a = Action Yeilding an a Action at the prompt is performed. The action returned by tick has a side-effect. Yields a different Integer each time it is performed.

  45. 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 no side-effects occurred.

  46. IO a = Action Yeilding an a twice2 :: 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 <- a return (x,y) The same action can be performed many times.

  47. References Variables in Haskell cannot be updated -- references can. newIORef :: a -> IO (IORef a) readIORef :: IORef a -> IO a writeIORef :: IORef a -> a -> IO () Reference operations have side-effects -- hence IO type.

  48. Example: Destructive List Insertion Updateable tail. 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' Must read the list cell. Create new cell and update old. case is inline pattern matching.

  49. 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] Array operations resemble reference ones. Use a hash table internally to make comparison fast. No IO type: no externally visible side-effects!

  50. Encapsulation: The ST Monad newSTRef :: a -> ST s (STRef s a) readSTRef :: STRef s a -> ST s a writeSTRef :: STRef s a -> a -> ST s () Similar family of operations.

More Related