1 / 43

CS5205: Foundations in Programming Languages FP with Haskell

CS5205: Foundations in Programming Languages FP with Haskell. A pure lazy functional language that embodies many innovative ideas in language design. Haskell. Advanced programming language – reusable , abstract , efficient, feature-rich . Functions and Expressions

earnestb
Download Presentation

CS5205: Foundations in Programming Languages FP with 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. CS5205: Foundations in Programming Languages FP with Haskell A pure lazy functional language that embodies many innovative ideas in language design. Haskell

  2. Haskell • Advanced programming language – reusable, abstract, efficient, feature-rich. • Functions and Expressions • Values, Types and Lazy evaluation • Products, Records and Algebraic Types • Polymorphic Types & Type Classes • Higher-Order Functions • Infix operator and sections. Reference --- A Gentle Introduction to Haskell 98 http://www.haskell.org/tutorial Haskell

  3. inputs inputs …. …. function function global vars output output …. …. impure Functions • Function is a black box that converts input to output. A basis of software component. pure Haskell

  4. Conversion from fahrenheit to celcius fahr_to_celcius :: Float -> Float fahr_to_celcius temp = (temp – 32)/1.8 • A function with multiple results - quotient & remainder divide :: Int -> Int -> (Int,Int) divide x y = (div x y, mod x y) Example of Functions • Double a given input. square :: Int -> Int square x = x*x Haskell

  5. Expression-Oriented • Instead of imperative commands/statements, the focus is on expression. • Instead of command/statement : • if e1 then stmt1 else stmt2 • We use conditional expressions : • if e1 then e2 else e3 Haskell

  6. Can use pattern-matching instead of conditional fact 0 = 1 fact n = n * fact (n-1) • Alternatively: fact n = case n of 0 -> 1 a -> a * fact (a-1) Expression-Oriented • An example function: fact :: Integer -> Integer fact n = if n=0 then 1 else n * fact (n-1) Haskell

  7. Case also works over data structures (without any extra primitives) length xs = case xs of [] -> 0; y:ys -> 1+(length ys) Locally bound variables Conditional  Case Construct • Conditional; • if e1 then e2 else e3 • Can be translated to case e1 of True -> e2 False -> e3 Haskell

  8. For scope bindings over guarded expressions, we require a where construct instead: f x y | x>z = … | y==z = … | y<z = …. where z=x*x Lexical Scoping • Local variables can be created by let construct to give nested scope for the name space. Example: let y = a+b f x = (x+y)/y in f c + f d Haskell

  9. Layout Rule • Haskell uses two dimensional syntax that relies on declarations being “lined-up columnwise” let y = a+b f x = (x+y)/y in f c + f d is being parsed as: let { y = a+b ; f x = (x+y)/y } in f c + f d • Rule : Next character after keywords where/let/of/dodetermines the starting columns for declarations. Starting after this point continues a declaration, while starting before this point terminates a declaration. Haskell

  10. A concrete example of this is: inc (inc 3)  inc (4)  5 Expression Evaluation • Expression can be computed (or evaluated) so that it is reduced to a value. This can be represented as: e  ..  v • We can abbreviate above as: e *v • Type preservation theorem says that: • if e :: tÆe v , it follows that v :: t Haskell

  11. Values and Types • As a purely functional language, all computations are done via evaluating expressions (syntactic sugar) to yield values (normal forms as answers). • Each expression has a type which denotes the set of possible outcomes. • v :: t can be read as value v has type t. • Examples of typings, associating a value with its corresponding type are: 5 :: Integer 'a' :: Char [1,2,3] :: [Integer] ('b', 4) :: (Char, Integer) “cs5” :: String (same as [Char]) Haskell

  12. Tuples are also built-in. data (a,b) = M2(a,b) data (a,b,c) = M3(a,b,c) data (a,b.c.d) = M4(a,b,c,d) • List type uses an infix operator: data [a] = [] | a : [a] [1,2,3] is short hand for 1 : (2 : (3 : [])) Built-In Types • They are not special: data Char = ‘a’ | ‘b’ | … data Int = -65532 | … | -1 | 0 | 1 | …. | 65532 data Integer = … | -2 | -1 | 0 | 1 | 2 | … Haskell

  13. Can also describe a tuple data Pair = P2 Integer Integer data Point a = Pt a a type variable • Pt is a data constructor with type a -> a -> Point a Pt 2.0 3.1 :: Point Float Pt ‘a’ ‘b’ :: Point Char Pt True False :: Point Bool User-Defined Algebraic Types • Can describe enumerations: data Bool = False | True data Color = Red | Green | Blue | Violet Haskell

  14. Two data constructors: Leaf :: a -> Tree a Branch :: Tree a -> Tree a -> Tree a • An example function over recursive types: fringe :: Tree a -> [a] fringe (Leaf x) = [x] fringe (Branch left right) = (fringe left) ++ (fringe right) Recursive Types • Some types may be recursive: data Tree a = Leaf a | Branch (Tree a) (Tree a) Haskell

  15. Polymorphism help support reusable code, e.g length :: 8 a. [a] -> Integer length [] = 0 length (x:xs) = 1 + length xs Polymorphic Types • Support types that are universally quantified in some way over all types. • 8 c. [c] denotes a family of types, for every type c, the type of lists of c. • Covers [Integer], [Char], [Integer->Integer], etc. Haskell

  16. More examples : head :: [a] -> a head (x:xs) = x tail :: [a] -> [a] tail (x:xs) = xs Polymorphic Types • This polymorphic function can be used on list of any type.. length [1,2,3] ) 2 length [‘a’, ’b’, ‘c’] ) 3 length [[1],[],[3]] ) 3 • Note that head/tail are partial functions, while length is a total function? Haskell

  17. Principal Types • Some types are more general than others: [Char] <: 8 a. [a] <: 8 a. a • An expression’s principal type is the least general type that contains all instances of the expression. • For example, the principal type of head function is • [a]->a, while [b] -> a, b -> a, a are correct but too general but [Integer] -> Integer is too specific. • Principal type can help supports software reusability with accurate type information. Haskell

  18. Type synonyms do not define new types, but simply give new names for existing types. type AssocList a b = [(a,b)] Type Synonyms • It is possible to provide new names for commonly used types type String = [Char] type Person = (Name, Address) type Name = String data Address = None | Addr String • Their use can improve code readability. Haskell

  19. For example, what is the type for (+) operator? (+) :: a -> a -> a (+) :: Int -> Int -> Int (+) :: Float -> Float -> Float • What about methods built from (+)? double x = x+x • Better solution is to use a type class for numerics! (+) :: Num a => a -> a -> a double :: Num a => a -> a Type Classes and Overloading • Parametric polymorphism works for all types. However, ad-hoc polymorphism works for a class of types and can systematically support overloading. Haskell

  20. Equality Class • Similar issue with equality. Though it looks like: (==) :: a -> a -> Bool • Equality can be tested for data structures but not functions! • Solution is to define a type class that supports the equality method, as follows: class Eq a where (==),(/=) :: a -> a -> Bool x /= y = not (x==y) default definition • Then: (==) :: Eq a => a -> a -> Bool Haskell

  21. Recursive type can also be handled but elements may need to be given type qualifiers. instance (Eq a) => Eq (Tree a) where Leaf a == Leaf b = a==b (Branch l1 r1) == (Branch l2 r2) = (l1==l2) && (r1==r2) _ == _ = False Members of Eq Type Class • The class is open and can be extended, as follows: instance Eq Integer where x == y = x ‘integerEq’ y instance Eq Float where x == y = x ‘FloatEq’ y Haskell

  22. More Members of Eq Type Class • Similarly, we may use structural equality for List: instance (Eq a) => Eq ([a]) where [] == [] = True (x:xs) == (y:ys) = (x==y) && (xs==ys) _ == _ = False • One use of Eq class is: elem :: (Eq a) => a -> [a] -> Bool x ‘elem’ [] = False x ‘elem’ (y:ys) = (x==y) || (x ‘elem’ ys) • Exercise : define Set as an instance of the Eq class. Haskell

  23. Numeric Class • There is a hierarchy of numeric classes. Most basic is: class Num a where (+),(-),(*) :: a -> a -> a negate,abs,signum :: a -> a fromInteger :: Integer -> a x – y = x + (negate y) negate x = 0 – x instance Num Int where … instance Num Integer where … instance Num Float where … instance Num Double where … Haskell

  24. Functions and its Type • Method to increment its input inc x = x+1 • Or through lambda expression (anonymous functions) (\ x -> x+1) • They can also be given suitable function typing: inc :: Num a => a -> a (\x -> x+1) :: Num a => a -> a • Types can be user-supplied or inferred. Haskell

  25. User can restrict the type, e.g. inc :: Int -> Int • In that case, some examples may be wrongly typed. inc 3.2  inc 3  Functions and its Type • Some examples (\x -> x+1) 3.2  (\x -> x+1) 3  Haskell

  26. Function Abstraction • Function abstraction is the ability to convert any expression into a function that is evaluated at a later time. <Expr> p = \ () -> Expr time p () time Normal Execution Delayed Execution Haskell

  27. Higher-Order Functions • Higher-order programming treats functions as first-class, allowing them to be passed as parameters, returned as results or stored into data structures. • This concept supports generic coding, and allows programming to be carried out at a more abstract level. • Genericity can be applied to a function by letting specific operation/value in the function body to become parameters. Haskell

  28. Functions • Functions can be written in two main ways: add :: Integer -> Integer -> Integer add x y = x+y add2 :: (Integer,Integer) -> Integer add2(x,y) = x+y • The first version allows a function to be returned as result after applying a single argument. inc :: Integer -> Integer inc = add 1 • The second version needs all arguments. Same effect requires a lambda abstraction: inc = \ x -> add2(x,1) Haskell

  29. Such higher-order function aids code reuse. map (add 1) [1, 2, 3] ) [2, 3, 4] map add [1, 2, 3] ) [add 1, add 2, add 3] • Alternative ways of defining functions: add = \ x -> \ y -> x+y add = \ x y -> x+y Functions • Functions can also be passed as parameters. Example: map :: (a->b) -> [a] -> [b] map f [] = [] map f (x:xs) = (f x) : (map f xs) Haskell

  30. foldr f u ls = case ls of [] -> u x:xs -> f x(foldr f u xs) Genericity • Replace specific entities (0 and +) by parameters. sumList ls = case ls of [] -> 0 x:xs -> x+(sumList xs) Haskell

  31. foldr :: (a -> b -> b) -> b -> [a] -> b Polymorphic, Higher-Order Types sumList :: [Int] -> Int sumList :: Num a => [a] -> a Haskell

  32. Instantiating Generic Functions sumL2 :: Num a => [a] -> a sumL2 ls = foldr (+)0 ls sumL2 [1, 2, 3] ) sumL2 [1.1, 3, 2.3] ) Haskell

  33. Instantiating Generic Functions prodL :: Num a => [a] -> a prodL ls = foldr (*)1 ls prodL [1, 2, 5] ) prodL [1.1, 3, 2.3] ) Haskell

  34. Instantiating Generic Functions • Can you express map in terms of foldr? map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = (f x) : (map f xs) map f xs = foldr … … … xs Haskell

  35. Can we express filter in terms of foldr? filter f xs = foldr … … … xs Instantiating Generic Functions • Filtering a list of elements with a predicate. filter :: (a -> Bool) -> [a] -> [a] filter f [] = [] filter f (x:xs) = if (f x) then x : (filter f xs) else x : filter f xs Haskell

  36. Similar to Unix pipe command: cmd1 | cmd2 Pipe/Compose compose :: (b -> c) -> (a -> b) -> a -> c compose f g = \ x -> f (g x) g | f = compose f g Haskell

  37. In Haskell, type class help give a more generic type: for :: Num b, Ord b => b -> b -> (b -> a -> a) -> a -> a Iterator Construct for :: Int -> Int -> (Int -> a -> a) -> a -> a for i j f a = if i>j then a else f (i+1) j (f i a) Haskell

  38. associate to right Right Folding foldr f u [x1,x2,..,xn] • f x1 (foldr f u [x2 ..xn]) • f x1 (f x2 (fold f u [x3..xn])) • f x1 (f x2 (… (fold f u [xn]) …)) • f x1 (f x2 (… (f xn u) …))) Haskell

  39. Left Folding – Tail Recursion • Accumulate result in a parameter: foldl f u ls = case ls of [] -> u x:xs -> foldl f (f u x) xs based on accumulation • What is the type of foldl? • Can we compute factorial using it? Haskell

  40. left is here! Left Folding foldl f u [x1,x2,..,xn] • foldl f (f u x1) [x2 ..xn] • foldl f (f (f u x1) x2) [x3..xn])) • foldl f (f … (f (f u x1) x2)… xn) [] • f (… (f (f u x1) x2) …) xn Haskell

  41. sumList ls = sumT 0 ls sumT acc ls = foldl (+) acc ls Instance of Left Folding • Summing a list by accumulation. sumT acc ls = case ls of [] -> 0 x:xs -> sumT (x+acc) xs Haskell

  42. Infix Operator • Infix operators are distinguished entirely by symbols: (++) :: [a]-> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) • Another example is function composition. (.) :: (b->c) -> (a->b) -> (a->c) f . g = \ x -> f (g x) • Infix operator can be coerced to prefix by bracketing, • e.g. map (+) [1,2,3] • Alphanumeric named function can be made infix too, • e.g. a ‘add’ b x ‘elem’ xs Haskell

  43. Sections • Infix operators can also be partially applied: (x+) ´ \y -> x+y (+y) ´ \x -> x+y (+) ´ \x y -> x+y • Other examples:. inc = (+ 1) add = (+) • These are syntactic sugar for programming conveniences. Haskell

More Related