Announcements n Rainbow grades: HW1-6, Quiz1-5, Exam1 n Still grading: HW7, Quiz6, Exam2 Intro to Haskell n HW8 due today n HW9, Haskell, out tonight, due Nov. 16 th n Individual assignment n Start early! Fall 18 CSCI 4430, A Milanova 1 Today s Lecture Outline n Haskell: a functional programming language n Key ideas n Rich syntax (syntactic sugar), rich libraries (modules) n Lazy evaluation n Static typing and polymorphic type inference n Algebraic data types and pattern matching n Type classes n Monads and more Fall 18 CSCI 4430, A Milanova 3 Haskell Resources n https://www.haskell.org/ n Try tutorial on front page to get started! n http://www.seas.upenn.edu/~cis194/ spring13/ n Stack Overflow! n Getting started: tutorial + slides Fall 18 CSCI 4430, A Milanova 4 Getting Started n Download the Glasgow Haskell Compiler: n https://www.haskell.org/ghc n Run Haskell in interactive mode: n ghci n Type functions in a file (e.g., fun.hs), then load the file and call functions interactively Prelude > :l fun.hs [1 of 1] Compiling Main ( fun.hs, interpreted ) Ok, one module loaded. *Main > square 25 5 Getting Started: Infix Syntax n You can use prefix syntax, like in Scheme: > ((+) 1 2) --- or (+) 1 2 3 --- (+) interprets + to function value > (quot 5 2) --- or quot 5 2 2 n Or you can use infix syntax: > 1 + 2 + 3 > 5 `quot` 2 --- function value to infix operator 6 1
Getting Started: Lists n Lists are important in Haskell too! > [1,2] [1,2] Syntactic sugar: > ana == [ a, n, a ] --- also, [ a, n, a ] == a : [ n... True --- strings are of type [Char], Char lists > map ((+) 1) [1,2] [2,3] n Caveat: in Haskell, all elements of a list must be of same type! You can t have [[1,2],2]! 7 Getting Started: Lists n map, foldl, foldr, filter and more are built-in! > foldl (+) 0 [1,2,3] 6 > foldr (-) 0 [1,2,3] 2 > filter ((<) 0) [-1,2,0,5] [2,5] Note: different order of arguments from ones we defined in Scheme. foldl : (b * a à b) * b * [a] à b In Haskell, functions are curried: foldl:: (b à a à b) à b à [a] à b à is right associative: a à b à c is a à (b à c) 8 Getting Started: Functions n Function definition: > square x = x*x --- name params = body n Evaluation: > square 5 25 n Anonymous functions: > map (\x->x+1) [1,2,3] --- \x-> is λx. [2,3,4] Fall 18 CSCI 4430, A Milanova 9 Getting Started: Functions n Function definition: > square x = x*x --- name params = body n Just as in Scheme, you can define a function using the lambda construct: > square = \x->x*x > square 5 Fall 18 CSCI 4430, A Milanova 10 Getting Started: Higher-order Functions n Of course, higher-order functions are everywhere! --- defining apply_n in ghci: > apply_n f n x = if n==0 then x else apply_n f (n-1) (f x) --- applies f n times on x: e.g., f (f (f (f x) > apply_n ((+) 1) 10 0 10 > fun a b = apply_n ((+) 1) a b Fall 18 CSCI 4430, A Milanova 11 Getting Started: Let Bindings n let in Haskell is same as letrec in Scheme: > let square x = x*x in square 5 25 > let lis = [ a, n, a ] in head lis a > let lis = [ a, n, a ] in tail lis na Fall 18 CSCI 4430, A Milanova 12 2
Getting Started: Indentation n Haskell supports ; and { } to delineate blocks n Haskell supports indentation too! iseven n = let Define function in file. Can t use indentation syntax in ghci! even n = if n == 0 then True else odd (n-1) odd n = if n == 0 then False else even (n-1) in even n > iseven 100 13 Interpreters for the Lambda Calculus (for HW9) n An interpreter for the lambda calculus is a program that reduces lambda expressions to answers n We must specify n Definition of answer. Which normal form? n Reduction strategy. How do we chose redexes in an expression? Fall 18 CSCI 4430, A Milanova 14 An Interpreter (HW9) Haskell syntax: let. in case f of à Another Interpreter (HW9) n Definition by cases on E ::= x λx. E 1 E 1 E 2 interpret(x) = x Apply the function interpret(λx.e 1 ) = λx.e before interpreting the 1 argument interpret(e 1 E 2 ) = let f = interpret(e 1 ) in case f of λx.e 3 à interpret(e 3 [E 2 /x]) - à f E 2 n What normal form: Weak head normal form n What strategy: Normal order Fall 18 CSCI 4430, A Milanova (modified from MIT 2015 Program Analysis OCW) 15 n Definition by cases on E ::= x λx. E 1 E 1 E 2 interpret(x) = x interpret(λx.e 1 ) = λx.e 1 interpret(e 1 E 2 ) = let f = interpret(e 1 ) a = interpret(e 2 ) in case f of λx.e 3 à interpret(e 3 [a/x]) - à f a n What normal form: Weak head normal form n What strategy: Applicative order 16 n In HW9 An Interpreter (HW9) n First, you will write the pseudocode for an interpreter that n Reduces to answers in Normal Form n n Uses applicative order reduction Then, you ll code this interpreter in Haskell Fall 18 CSCI 4430, A Milanova 17 Lecture Outline n Haskell: a functional programming language n Key ideas n Rich syntax, rich libraries (modules) n Lazy evaluation n Static typing and polymorphic type inference n Algebraic data types and pattern matching n Type classes n Monads and more Fall 18 CSCI 4430, A Milanova 18 3
Lazy Evaluation n Unlike Scheme (and most programming languages) Haskell does lazy evaluation, i.e., normal order reduction n It won t evaluate an expression until it is needed > f x = [] --- f takes x and returns the empty list > f (repeat 1) --- repeat produces infinite list [1,1 > [] > head ([1..]) --- [1..] is the infinite list of integers > 1 n Lazy evaluation allows work with infinite structures! 19 Lazy Evaluation > f x = x*x > f (5+1) --- evaluates to (5+1) * (5+1) --- evaluates argument only when needed > fun n = n : fun(n+1) > head (fun 5) : denotes cons : constructs a list with head n and tail fun(n-1) n Exercise: write a function that returns the (infinite) list of prime numbers 20 Static Typing and Type Inference n Unlike Scheme, which is dynamically typed, Haskell is statically typed! n Unlike Java/C++ we don t have to write type annotations. Haskell infers types! > let f x = head x in f True Couldn't match expected type [a] with actual type Bool In the first argument of f, namely True In the expression: f True 21 Static Typing and Type Inference n Recall apply_n f n x: > apply_n f n x = if n==0 then x else apply_n f (n-1) (f x) > apply_n ((+) 1) True 0 <interactive>:32:1: error: Could not deduce (Num Bool) arising from a use of apply_n from the context: Num t2 bound by the inferred type of it :: Num t2 => t2 at <interactive>:32:1-22 In the expression: apply_n ((+) 1) True 0 In an equation for it : it = apply_n ((+) 1) True 0 22 Algebraic Data Types n Algebraic data types are tagged unions (aka sums) of products (aka records) data Shape = Line Point Point Triangle Point Point Point Quad Point Point Point Point union Algebraic Data Types n Constructors create values of the data type let l1::shape l1 = Line e1 e2 Haskell keyword the new type new constructors (a.k.a. tags, disjuncts, summands) Line is a binary constructor, Triangle is a ternary Fall 18 CSCI 4430, A Milanova (example from MIT 2015 Program Analysis OCW) 23 t1::shape = Triangle e3 e4 e5 q1::shape = Quad e6 e7 e8 e9 in Fall 18 CSCI 4430, A Milanova (example from MIT 2015 Program Analysis OCW) 24 4
Algebraic Data Types in HW9 n Defining a lambda expression type Name = String data Expr = Var Name Lambda Name Expr App Expr Expr > e1 = Var x // Lambda term x > e2 = Lambda x e1 // Lambda term λx.x Fall 18 CSCI 4430, A Milanova 25 Exercise: Define an ADT for Expressions in your Scheme HW6 type Name = String data Expr = Var Name Val Bool And Expr Expr Or Expr Expr Let Name Expr Expr evaluate :: Expr à [(Name,Bool)] à Bool evaluate e env = Fall 18 CSCI 4430, A Milanova 26 Examples of Algebraic Data Types data Bool = True False data Day = Mon Tue Wed Thu Fri Sat Sun data List a = Nil Cons a (List a) data Tree a = Leaf a Node (Tree a) (Tree a) data Maybe a = Nothing Just a Polymorphic types. a is a type parameter! Maybe type denotes that result of computation can be a or Nothing. Maybe is a monad. Fall 18 CSCI 4430, A Milanova (examples from MIT 2015 Program Analysis OCW) 27 Pattern Matching Type signature of anchorpnt: takes a Shape and returns a Point. n Examine values of an algebraic data type anchorpnt :: Shape -> Point anchorpnt s = case s of Line p1 p2 -> p1 Triangle p3 p4 p5 -> p3 Quad p6 p7 p8 p9 -> p6 n Two points n Test: does the given value match this pattern? n Binding: if value matches, bind corresponding values of s and pattern Fall 18 CSCI 4430, A Milanova (from MIT 2015 Program Analysis OCW) 28 Pattern Matching n Pattern matching deconstructs a term > let h:t = "ana" in t na > let (x,y) = (10, ana ) in x 10 Fall 18 CSCI 4430, A Milanova 29 Pattern Matching in HW9 isfree::name à Expr à Bool isfree v e = case e of Var n à if (n == v) then True else False Lambda Type signature of isfree. In Haskell, all functions are curried, i.e., they take just one argument. isfree takes a variable name, and returns a function that takes an expression and returns a boolean. Of course, we can interpret isfree as a function that takes a variable name name and an expression E, and returns true if variable name is free in E. Fall 18 CSCI 4430, A Milanova 30 5
Generic Functions in Haskell n We can generalize a function when a function makes no assumptions about the type: const :: a -> b -> a const x y = x apply :: (a->b)->a->b apply g x = g x Fall 18 CSCI 4430, A Milanova (examples from MIT 2015 Program Analysis OCW) 31 Generic Functions -- List datatype data List a = Nil Cons a (List a) n Can we have sum of parameterized type? sum :: a -> List a -> a sum n Nil = n sum n (Cons x xs) = sum (n+x) xs n No. a no longer unconstraint. Type and function definition imply that + is of type a->a->a but n + is not defined for all types! 32 Haskell Type Classes n Define a type class containing the arithmetic operators class Num a where (==) :: a -> a -> Bool (+) :: a -> a -> a instance Num Int where x == y =...... instance Num Float where Read: A type a is an instance of the type class Num if it provides overloaded definitions of operations ==, +, Read: Int and Float are instances of Num Generic Functions with Type Class sum :: (Num a) => a -> List a -> a sum n Nil = n sum n (Cons x xs) = sum (n+x) xs n One view of type classes: predicates n (Num a) is a predicate in type definitions n Constrains the types we can instantiate a generic function to specific types n A type class has associated laws Fall 18 CSCI 4430, A Milanova 33 Fall 18 CSCI 4430, A Milanova 34 Type Class Hierarchy Lecture Outline class Eq a where (==), (/=) :: a -> a -> Bool n Haskell: a functional programming language class (Eq a) => Ord where (<), (<=), (>), (>=) :: a -> a -> Bool min, max :: a -> a -> a n Each type class corresponds to one concept n Class constraints give rise to a hierarchy n Eq is a superclass of Ord n Ord inherits specification of (==) and (/=) n Notion of true subtyping Fall 18 CSCI 4430, A Milanova (modified from MIT 2015 Program Analysis OCW) 35 n Key ideas n Rich syntax, rich libraries (modules) n Lazy evaluation n Static typing and polymorphic type inference n Algebraic data types and pattern matching n Type classes n Monads and more Fall 18 CSCI 4430, A Milanova 36 6
Monads n A way to cleanly compose computations n E.g., f may return a value of type a or Nothing Composing computations becomes tedious: case (f s) of Nothing à Nothing Just m à case (f m) n In Haskell, monads encapsulate IO and other imperative features Fall 18 CSCI 4430, A Milanova 37 An Example: Cloned Sheep type Sheep = father :: Sheep à Maybe Sheep father =... mother :: Sheep à Maybe Sheep mother = (Note: a cloned sheep may have both parents, or not...) maternalgrandfather :: Sheep à Maybe Sheep maternalgrandfather s = case (mother s) of Nothing à Nothing Just m à father m Fall 18 CSCI 4430, A Milanova (Example from All About Monads Tutorial) 38 An Example The Monad Type Class motherspaternalgrandfather :: Sheep à Maybe Sheep motherspaternalgrandfather s = case (mother s) of Nothing à Nothing Just m à case (father m) of Nothing à Nothing Just gf à father gf n Tedious, unreadable, difficult to maintain n Monads help! Fall 18 CSCI 4430, A Milanova (Example from All About Monads Tutorial) 39 n Haskell s Monad class requires 2 operations, >>= (bind) and return class Monad m where // >>= (the bind operation) takes a monad // m a, and a function that takes a and turns // it into a monad m b (>>=) :: m a à (a à m b) à m b // return encapsulates a value into the monad return :: a à m a 40 The Maybe Monad The List Monad instance Monad Maybe where Nothing >>= f = Nothing (Just x) >>= f = f x return = Just n Cloned Sheep example: motherspaternalgrandfather s = (return s) >>= mother >>= father >>= father (Note: if at any point, some function returns Nothing, Nothing gets cleanly propagated.) 41 n The List type constructor is a monad li >>= f = concat (map f li) return x = [x] Note: concat::[[a]] à [a] e.g., concat [[1,2],[3,4],[5,6]] yields [1,2,3,4,5,6] n Use any f s.t. f::aà[b]. f may yield a list of 0,1,2, elements of type b, e.g., > f x = [x+1] > [1,2,3] >>= f --- yields [2,3,4] 42 7
The List Monad parents :: Sheep à [Sheep] parents s = MaybeToList (mother s) ++ MaybeToList (father s) grandparents :: Sheep à [Sheep] grandparents s = (parents s) >>= parents The do Notation (Syntactic Sugar!) > f x = x+1 > g x = x*5 > [1,2,3] >>= (return. f) >>= (return. g) Or > [1,2,3] >>= (return. \x->x+1) >>= (return. \y->y*5) Or > do { x <- [1,2,3]; y <- (return. f) x; (return. g) y } Fall 18 CSCI 4430, A Milanova 43 44 List Comprehensions > [ x x <- [1,2,3,4] ] [1,2,3,4] > [ x x <- [1,2,3,4], x `mod` 2 == 0 ] [2,4] > [ [x,y] x <- [1,2,3], y <- [6,5,4] ] [[1,6],[1,5],[1,4],[2,6],[2,5],[2,4],[3,6],[3,5],[3,4]] --- Willy s all-pairs function from test Fall 18 CSCI 4430, A Milanova 45 List Comprehensions n List comprehensions are syntactic sugar [ x x <- [1,2,3,4] ] is syntactic sugar for do { x <- [1,2,3,4]; return x } [ [x,y] x <- [1,2,3], y <- [6,5,4] ] synt. sugar for do { x <- [1,2,3]; y<-[6,5,4]; return [x,y] } Fall 18 CSCI 4430, A Milanova 46 Monads n A way to cleanly compose (build) computations n A way to encapsulate IO and other imperative features Fall 18 CSCI 4430, A Milanova 47 Spring 18 CSCI 4450/6450, A Milanova 48 8