Save this PDF as:

Size: px
Start display at page:

## Transcription

1 INTRODUCTION TO HASKELL PRINCIPLES OF PROGRAMMING LANGUAGES Norbert Zeh Winter 2018 Dalhousie University 1/81

2 HASKELL: A PURELY FUNCTIONAL PROGRAMMING LANGUAGE Functions are first-class values: Can be passed as function arguments, returned from functions. 2/81

3 HASKELL: A PURELY FUNCTIONAL PROGRAMMING LANGUAGE Functions are first-class values: Can be passed as function arguments, returned from functions. Variables are (normally) immutable. 2/81

4 HASKELL: A PURELY FUNCTIONAL PROGRAMMING LANGUAGE Functions are first-class values: Can be passed as function arguments, returned from functions. Variables are (normally) immutable. Deeply grounded in the mathematics of computing. 2/81

5 HASKELL: A PURELY FUNCTIONAL PROGRAMMING LANGUAGE Functions are first-class values: Can be passed as function arguments, returned from functions. Variables are (normally) immutable. Deeply grounded in the mathematics of computing. Effectful computations are modelled in a functional manner. 2/81

6 HASKELL: A PURELY FUNCTIONAL PROGRAMMING LANGUAGE Functions are first-class values: Can be passed as function arguments, returned from functions. Variables are (normally) immutable. Deeply grounded in the mathematics of computing. Effectful computations are modelled in a functional manner. Elegant and concise. 2/81

7 VALUES AND FUNCTIONS In Haskell, functions are values and values are (nullary) functions. 3/81

8 VALUES AND FUNCTIONS In Haskell, functions are values and values are (nullary) functions. C++: int x = 2; Haskell: x :: Int x = 2 3/81

9 VALUES AND FUNCTIONS In Haskell, functions are values and values are (nullary) functions. C++: int x = 2; int x() { return 2; } Haskell: x :: Int x = 2 x :: Int x = 2 3/81

10 VALUES AND FUNCTIONS In Haskell, functions are values and values are (nullary) functions. C++: int x = 2; int x() { return 2; } int add(int x, int y) { return x + y; } Haskell: x :: Int x = 2 x :: Int x = 2 add :: Int -> Int -> Int add x y = x + y 3/81

11 LOCAL VARIABLES Local variables are useful in many programming languages to store intermediate results. Haskell is no different. The following two pieces of code behave identically: veclen :: (Float, Float) -> Float veclen (x, y) = sqrt(xx + yy) where xx = x * x yy = y * y veclen :: (Float, Float) -> Float veclen (x, y) = let xx = x * x yy = y * y in sqrt(xx + yy) 4/81

12 VARIABLES ARE IMMUTABLE C++: int four() { int x = 2; x = x + 2; return x; } Haskell: four :: Int four = x where x = 2 x = x + 2 returns 4. gives a compile-time error. 5/81

13 VARIABLES ARE IMMUTABLE C++: int four() { int x = 2; x = x + 2; return x; } Haskell: four :: Int four = x2 where x1 = 2 x2 = x1 + 2 returns 4. works. 5/81

14 VARIABLES ARE IMMUTABLE C++: int four() { int x = 2; x = x + 2; return x; } Haskell: four :: Int four = x2 where x2 = x1 + 2 x1 = 2 returns 4. also works. 5/81

15 CONTROL CONSTRUCTS if-then-else: abs :: Int -> Int abs x = if x < 0 then (-x) else x 6/81

16 CONTROL CONSTRUCTS if-then-else: abs :: Int -> Int abs x = if x < 0 then (-x) else x The else-branch is mandatory! Why? 6/81

17 CONTROL CONSTRUCTS if-then-else: abs :: Int -> Int abs x = if x < 0 then (-x) else x case: is-two-or-five :: Int -> Bool is-two-or-five x = case x of 2 -> True 5 -> True _ -> False The else-branch is mandatory! Why? 6/81

18 CONTROL CONSTRUCTS if-then-else: abs :: Int -> Int abs x = if x < 0 then (-x) else x The else-branch is mandatory! Why? case: is-two-or-five :: Int -> Bool is-two-or-five x = case x of 2 -> True 5 -> True _ -> False _ is a wildcard that matches any value. 6/81

19 PATTERNS fibonacci :: Int -> Int fibonacci n = case n of 0 -> 1 1 -> 1 _ -> fibonacci (n-1) + fibonacci (n-2) 7/81

20 PATTERNS fibonacci :: Int -> Int fibonacci n = case n of 0 -> 1 1 -> 1 _ -> fibonacci (n-1) + fibonacci (n-2) Idiomatic Haskell uses multiple function definitions for this: fibonacci 0 = 1 fibonacci 1 = 1 fibonacci n = fibonacci (n-1) + fibonacci (n-2) 7/81

21 PATTERNS fibonacci :: Int -> Int fibonacci n = case n of 0 -> 1 1 -> 1 _ -> fibonacci (n-1) + fibonacci (n-2) Idiomatic Haskell uses multiple function definitions for this: fibonacci 0 = 1 fibonacci 1 = 1 fibonacci n = fibonacci (n-1) + fibonacci (n-2) Pattern matching: The first equation whose formal arguments match the arguments of the invocation is used. 7/81

22 PATTERNS fibonacci :: Int -> Int fibonacci n = case n of 0 -> 1 1 -> 1 _ -> fibonacci (n-1) + fibonacci (n-2) Idiomatic Haskell uses multiple function definitions for this: fibonacci n = fibonacci (n-1) + fibonacci (n-2) fibonacci 0 = 1 This gives an infinite loop! fibonacci 1 = 1 Pattern matching: The first equation whose formal arguments match the arguments of the invocation is used. 7/81

23 PATTERN GUARDS Pattern guards: Patterns can be combined with conditions on when they match. abs :: Int -> Int abs x x < 0 = -x otherwise = x 8/81

24 PATTERN GUARDS Pattern guards: Patterns can be combined with conditions on when they match. abs :: Int -> Int abs x x < 0 = -x otherwise = x sign :: Int -> Int sign 0 = 0 sign x x < 0 = -1 otherwise = 1 8/81

25 PATTERN GUARDS Pattern guards: Patterns can be combined with conditions on when they match. abs :: Int -> Int abs x x < 0 = -x otherwise = x sign :: Int -> Int sign 0 = 0 sign x x < 0 = -1 otherwise = 1 Pattern guards can also be applied to branches of a case-statement. 8/81

26 LOOPS? Loops are impossible in a functional language. Why? 9/81

27 LOOPS? Loops are impossible in a functional language. Why? What about iteration? 9/81

28 LOOPS? Loops are impossible in a functional language. Why? What about iteration? Iteration becomes recursion. 9/81

29 LOOPS? Loops are impossible in a functional language. Why? What about iteration? Iteration becomes recursion. Iterative C++: int factorial(int n) { int fac = 1; for (int i = 1; i <= n; ++i) fac *= i; return fac; } 9/81

30 LOOPS? Loops are impossible in a functional language. Why? What about iteration? Iteration becomes recursion. Iterative C++: int factorial(int n) { int fac = 1; for (int i = 1; i <= n; ++i) fac *= i; return fac; } Recursive C++: int factorial(int n) { if (n <= 1) return 1; else return n * factorial(n-1); } 9/81

31 LOOPS? Loops are impossible in a functional language. Why? What about iteration? Iteration becomes recursion. Iterative C++: int factorial(int n) { int fac = 1; for (int i = 1; i <= n; ++i) fac *= i; return fac; } Recursive C++: int factorial(int n) { if (n <= 1) return 1; else return n * factorial(n-1); } Haskell: factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial (n-1) 9/81

32 LOOPS? Loops are impossible in a functional language. Why? What about iteration? Iteration becomes recursion. Iterative C++: Efficient int factorial(int n) { int fac = 1; for (int i = 1; i <= n; ++i) fac *= i; return fac; } Recursive C++: Inefficient int factorial(int n) { if (n <= 1) return 1; else return n * factorial(n-1); } Haskell: Inefficient factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial (n-1) 9/81

33 MAKING RECURSION EFFICIENT: TAIL RECURSION Tail recursion: When the last statement in a function is a recursive invocation of the same function, the compiler converts these recursive calls into a loop. 10/81

34 MAKING RECURSION EFFICIENT: TAIL RECURSION Tail recursion: When the last statement in a function is a recursive invocation of the same function, the compiler converts these recursive calls into a loop. Not tail-recursive: factorial 0 = 1 factorial n = n * factorial (n-1) 10/81

35 MAKING RECURSION EFFICIENT: TAIL RECURSION Tail recursion: When the last statement in a function is a recursive invocation of the same function, the compiler converts these recursive calls into a loop. Not tail-recursive: factorial 0 = 1 factorial n = n * factorial (n-1) Tail-recursive: factorial n = factorial' n 1 factorial' 0 f = f factorial' n f = factorial' (n-1) (n*f) 10/81

36 MAKING RECURSION EFFICIENT: TAIL RECURSION Tail recursion: When the last statement in a function is a recursive invocation of the same function, the compiler converts these recursive calls into a loop. Not tail-recursive: factorial 0 = 1 factorial n = n * factorial (n-1) Stack size = depth of recursion Overhead to maintain the stack Tail-recursive: factorial n = factorial' n 1 factorial' 0 f = f factorial' n f = factorial' (n-1) (n*f) 10/81

37 MAKING RECURSION EFFICIENT: TAIL RECURSION Tail recursion: When the last statement in a function is a recursive invocation of the same function, the compiler converts these recursive calls into a loop. Not tail-recursive: factorial 0 = 1 factorial n = n * factorial (n-1) Stack size = depth of recursion Overhead to maintain the stack Tail-recursive: factorial n = factorial' n 1 factorial' 0 f = f factorial' n f = factorial' (n-1) (n*f) Constant stack size No overhead to maintain the stack 10/81

38 DATA TYPES Primitive types: Int, Rational, Float, Char Collection types: Lists, tuples, arrays, String (list of Char) Custom types: Algebraic types (similar to struct in C) Type aliases (similar to typedef in C) 11/81

39 LISTS Lists are ubiquitous in Haskell because they match the recursive world view of functional languages: A list Is empty or Consists of an element, its head, followed by a list, its tail. 12/81

40 LISTS Lists are ubiquitous in Haskell because they match the recursive world view of functional languages: A list Is empty or Consists of an element, its head, followed by a list, its tail. In Haskell: emptylist = [] oneelementlist = 1 : emptylist twoelementlist = 2 : oneelementlist twoelementlist oneelementlist emptylist 2 1 null 12/81

41 LIST COMPREHENSIONS [1, 2, 3] 13/81

42 LIST COMPREHENSIONS [1, 2, 3] [1.. 10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 13/81

43 LIST COMPREHENSIONS [1, 2, 3] [1.. 10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1..] -- the infinite list [1, 2, 3,...] 13/81

44 LIST COMPREHENSIONS [1, 2, 3] [1.. 10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1..] -- the infinite list [1, 2, 3,...] [2, ] -- [2, 4, 6, 8, 10] 13/81

45 LIST COMPREHENSIONS [1, 2, 3] [1.. 10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1..] -- the infinite list [1, 2, 3,...] [2, ] -- [2, 4, 6, 8, 10] [(x, y) x <- [0..8], y <- [0..8], even x even y] -- The list of coordinates /81

46 POLYMORPHISM (1) Many functions and data types in Haskell are polymorphic (can be applied to arbitrary types, in a type-safe manner). 14/81

47 POLYMORPHISM (1) Many functions and data types in Haskell are polymorphic (can be applied to arbitrary types, in a type-safe manner). The idea is the same as generics/templates, but the use is more light-weight: 14/81

48 POLYMORPHISM (1) Many functions and data types in Haskell are polymorphic (can be applied to arbitrary types, in a type-safe manner). The idea is the same as generics/templates, but the use is more light-weight: C++/Java/Scala: Do I have a good enough reason to implement this function or class as a generic/template? 14/81

49 POLYMORPHISM (1) Many functions and data types in Haskell are polymorphic (can be applied to arbitrary types, in a type-safe manner). The idea is the same as generics/templates, but the use is more light-weight: C++/Java/Scala: Do I have a good enough reason to implement this function or class as a generic/template? Haskell: Do I have a good reason not to make this function or type polymorphic? 14/81

50 POLYMORPHISM (2) C++: template <typename T> std::vector<t> concat(const std::vector<t> &xs, const std::vector<t> &ys) { std::vector<t> result(xs); for (auto &y : ys) result.push_back(y); return result; } 15/81

51 POLYMORPHISM (2) C++: template <typename T> std::vector<t> concat(const std::vector<t> &xs, const std::vector<t> &ys) { std::vector<t> result(xs); for (auto &y : ys) result.push_back(y); return result; } Haskell: concat :: [t] -> [t] -> [t] concat [] ys = ys concat (x:xs) ys = x : concat xs ys 15/81

52 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } 16/81

53 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } (Relatively) obscure message when using the template with a type T that does not support addition. 16/81

54 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } Haskell: sum :: [t] -> t sum [] = 0 sum (x:xs) = x + sum xs (Relatively) obscure message when using the template with a type T that does not support addition. 16/81

55 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } Haskell: sum :: [t] -> t sum [] = 0 sum (x:xs) = x + sum xs (Relatively) obscure message when using the template with a type T that does not support addition. Function must specify what interface it expects from its argument types. 16/81

56 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } Haskell: sum :: [t] -> t sum [] = 0 sum (x:xs) = x + sum xs sum :: Num t => [t] -> t sum [] = 0 sum (x:xs) = x + sum xs (Relatively) obscure message when using the template with a type T that does not support addition. Function must specify what interface it expects from its argument types. 16/81

57 MAKING POLYMORPHISM TYPE-SAFE: TYPE CLASSES C++: template <typename T> T sum(const std::vector<t> &xs) { T total = 0; for (auto x : xs) total += x; return total; } Haskell: sum :: [t] -> t sum [] = 0 sum (x:xs) = x + sum xs sum :: Num t => [t] -> t sum [] = 0 sum (x:xs) = x + sum xs (Relatively) obscure message when using the template with a type T that does not support addition. Function must specify what interface it expects from its argument types. Use of function not satisfying type constraints reported upon use. 16/81

58 COMMON TYPE CLASSES Eq: Supports equality testing using == and /= Ord: (Requires Eq) Supports ordering using <, >, <=, and >= Num: Supports +, -, *, abs,, not /! Show: Supports conversion to a string using show Read: Supports conversion from a string using read 17/81

59 DECONSTRUCTING LISTS Inspecting the contents of lists is often done using patterns, but we can also explicitly ask for the head or tail of a list: head :: [t] -> t head (x:_) = x head _ = error "Cannot take head of empty list" tail :: [t] -> t tail (_:xs) = xs tail _ = error "Cannot take tail of empty list" 18/81

60 MORE LIST FUNCTIONS -- Concatenate two lists [1, 2] ++ [3, 4, 5] == [1.. 5] 19/81

61 MORE LIST FUNCTIONS -- Concatenate two lists [1, 2] ++ [3, 4, 5] == [1.. 5] -- Concatenate a list of lists concat [[1, 2], [3], [4, 5]] == [1.. 5] 19/81

62 MORE LIST FUNCTIONS -- Concatenate two lists [1, 2] ++ [3, 4, 5] == [1.. 5] -- Concatenate a list of lists concat [[1, 2], [3], [4, 5]] == [1.. 5] -- Take the first 5 elements of the list take 5 [1.. 10] == [1.. 5] 19/81

63 MORE LIST FUNCTIONS -- Concatenate two lists [1, 2] ++ [3, 4, 5] == [1.. 5] -- Concatenate a list of lists concat [[1, 2], [3], [4, 5]] == [1.. 5] -- Take the first 5 elements of the list take 5 [1.. 10] == [1.. 5] -- Drop the first 5 elements of the list drop 5 [1.. 10] == [6.. 10] 19/81

64 MORE LIST FUNCTIONS -- Concatenate two lists [1, 2] ++ [3, 4, 5] == [1.. 5] -- Concatenate a list of lists concat [[1, 2], [3], [4, 5]] == [1.. 5] -- Take the first 5 elements of the list take 5 [1.. 10] == [1.. 5] -- Drop the first 5 elements of the list drop 5 [1.. 10] == [6.. 10] -- Split the list after the 5th element splitat 5 [1.. 10] = ([1.. 5], [6.. 10]) 19/81

65 TUPLES Lists can hold an arbitrary number of elements of the same type: l = [1.. 10] -- l :: [Int] l' = 'a' : l -- error! Tuples can hold a fixed number of elements of potentially different types: t = ('a', 1, [2, 3]) -- t :: (Char, Int, [Int]) 20/81

66 OPERATIONS FOR PAIRS AND TUPLES fst :: (a, b) -> a snd :: (a, b) -> b fst (x, _) = x snd (_, y) = y 21/81

67 OPERATIONS FOR PAIRS AND TUPLES fst :: (a, b) -> a snd :: (a, b) -> b fst (x, _) = x snd (_, y) = y (,) :: a -> b -> (a, b) (,) x y = (x, y) 21/81

68 OPERATIONS FOR PAIRS AND TUPLES fst :: (a, b) -> a snd :: (a, b) -> b fst (x, _) = x snd (_, y) = y (,) :: a -> b -> (a, b) (,) x y = (x, y) (,,,) :: a -> b -> c -> d -> (a, b, c, d) (,,,) w x y z = (w, x, y, z) 21/81

69 LISTS AND TUPLES: THE FANTASTIC DUO Zipping and unzipping: From a pair of lists to a list of pairs and back. zip ['a', 'b', 'c'] [1.. 10] == [('a',1), ('b',2), ('c',3)] -- The result has the length of the shorter of the two lists 22/81

70 LISTS AND TUPLES: THE FANTASTIC DUO Zipping and unzipping: From a pair of lists to a list of pairs and back. zip ['a', 'b', 'c'] [1.. 10] == [('a',1), ('b',2), ('c',3)] -- The result has the length of the shorter of the two lists unzip [('a',1), ('b',2), ('c',3)] = (['a', 'b', 'c'], [1, 2, 3]) 22/81

71 LISTS AND TUPLES: THE FANTASTIC DUO Zipping and unzipping: From a pair of lists to a list of pairs and back. zip ['a', 'b', 'c'] [1.. 10] == [('a',1), ('b',2), ('c',3)] -- The result has the length of the shorter of the two lists unzip [('a',1), ('b',2), ('c',3)] = (['a', 'b', 'c'], [1, 2, 3]) Zipping with a function: zipwith (\x y -> x + y) [1, 2, 3] [4, 5, 6] == [5, 7, 9] 22/81

72 ARRAYS (1) Arrays do exist in Haskell and do have their uses because they support constant-time access. However, arrays are (normally) immutable, so updates are expensive. 23/81

73 ARRAYS (1) Arrays do exist in Haskell and do have their uses because they support constant-time access. However, arrays are (normally) immutable, so updates are expensive. Creating arrays: array (1,3) [(3,'a'), (1,'b'), (2,'c')] b c a /81

74 ARRAYS (1) Arrays do exist in Haskell and do have their uses because they support constant-time access. However, arrays are (normally) immutable, so updates are expensive. Creating arrays: array (1,3) [(3,'a'), (1,'b'), (2,'c')] b c a listarray ('a','c') [3,1,2] a b c 23/81

75 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] 24/81

76 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] a! 1 == 'a' a! 3 == 'c' 24/81

77 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] a! 1 == 'a' a! 3 == 'c' elems a == ['a', 'b', 'c'] 24/81

78 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] a! 1 == 'a' a! 3 == 'c' elems a == ['a', 'b', 'c'] assocs a == [(1,'a'), (2,'b'), (3,'c')] 24/81

79 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] a! 1 == 'a' a! 3 == 'c' elems a == ['a', 'b', 'c'] assocs a == [(1,'a'), (2,'b'), (3,'c')] Updating arrays: a // [(2,'a'), (1,'d')] == listarray (1,3) ['d', 'a', 'c'] 24/81

80 ARRAYS (2) Accessing array elements: let a = listarray (1,3) ['a', 'b', 'c'] a! 1 == 'a' a! 3 == 'c' elems a == ['a', 'b', 'c'] assocs a == [(1,'a'), (2,'b'), (3,'c')] Updating arrays: a // [(2,'a'), (1,'d')] == listarray (1,3) ['d', 'a', 'c'] (//) does not update the original array but creates a new array with the specified elements changed. Why? 24/81

81 ARRAYS: A MORE INTERESTING EXAMPLE Counting characters in a text: countchars :: String -> [(Char, Int)] countchars txt = filter nonzero (assocs counts) where counts = accumarray (+) 0 ('a','z') (zip txt (repeat 1)) nonzero (_, c) = c > 0 countchars "mississippi" == [('i',4), ('m',1), ('p',2), ('s',4)] 25/81

82 CUSTOM ALGEBRAIC DATA TYPES Custom algebraic data types (similar to classes/structs) are defined using data. 26/81

83 CUSTOM ALGEBRAIC DATA TYPES Custom algebraic data types (similar to classes/structs) are defined using data. A simple enum type: data Colors = Red Green Blue 26/81

84 CUSTOM ALGEBRAIC DATA TYPES Custom algebraic data types (similar to classes/structs) are defined using data. A simple enum type: data Colors = Red Green Blue deriving (Eq, Ord, Ix) 26/81

85 CUSTOM ALGEBRAIC DATA TYPES Custom algebraic data types (similar to classes/structs) are defined using data. A simple enum type: data Colors = Red Green Blue deriving (Eq, Ord, Ix) A binary tree: data Tree t = Leaf Node { item :: t, left, right :: Tree t } 26/81

86 CUSTOM ALGEBRAIC DATA TYPES Custom algebraic data types (similar to classes/structs) are defined using data. A simple enum type: data Colors = Red Green Blue deriving (Eq, Ord, Ix) A binary tree: data Tree t = Leaf Node { item :: t, left, right :: Tree t } fun1 (Tree x l r) = work with x, l, and r fun2 tree = work with (item tree), (left tree), -- and (right tree) upditem tree x = tree { item = x } 26/81

87 WHEN DATA IS TOO COSTLY Type aliases similar to typedef or using in C/C++ are defined using type: type Point = (Float, Float) type PointList = [Point] Point and (Float, Float) can be used 100% interchangeably. 27/81

88 WHEN DATA IS TOO COSTLY Type aliases similar to typedef or using in C/C++ are defined using type: type Point = (Float, Float) type PointList = [Point] Point and (Float, Float) can be used 100% interchangeably. IDs are integers but adding or multiplying them makes no sense: newtype ID = ID Int deriving (Eq, Ord) 27/81

89 WHEN DATA IS TOO COSTLY Type aliases similar to typedef or using in C/C++ are defined using type: type Point = (Float, Float) type PointList = [Point] Point and (Float, Float) can be used 100% interchangeably. IDs are integers but adding or multiplying them makes no sense: newtype ID = ID Int deriving (Eq, Ord) Internally, an ID is represented as an integer. With data, there would have been some space overhead. 27/81

90 WHEN DATA IS TOO COSTLY Type aliases similar to typedef or using in C/C++ are defined using type: type Point = (Float, Float) type PointList = [Point] Point and (Float, Float) can be used 100% interchangeably. IDs are integers but adding or multiplying them makes no sense: newtype ID = ID Int deriving (Eq, Ord) Internally, an ID is represented as an integer. With data, there would have been some space overhead. Without the deriving clause, ID does not support any operations. 27/81

91 WHEN DATA IS TOO COSTLY Type aliases similar to typedef or using in C/C++ are defined using type: type Point = (Float, Float) type PointList = [Point] Point and (Float, Float) can be used 100% interchangeably. IDs are integers but adding or multiplying them makes no sense: newtype ID = ID Int deriving (Eq, Ord) Internally, an ID is represented as an integer. With data, there would have been some space overhead. Without the deriving clause, ID does not support any operations. The deriving clause says that IDs should inherit equality and ordering from its underlying type. 27/81

92 @-PATTERNS fun1 (Tree x l r) = work with x, l, and r fun2 tree = work with (item tree), (left tree), fun1 can refer to the parts of the tree but not to the whole tree. fun2 has access to the whole tree but needs to take extra steps to access its parts. Sometimes, we d like to have both. 28/81

93 @-PATTERNS fun1 (Tree x l r) = work with x, l, and r fun2 tree = work with (item tree), (left tree), fun1 can refer to the parts of the tree but not to the whole tree. fun2 has access to the whole tree but needs to take extra steps to access its parts. Sometimes, we d like to have both. Merging two sorted lists: merge :: Ord t => [t] -> [t] -> [t] merge [] ys = ys merge xs [] = xs merge y < x = y : merge xs ys' otherwise = x : merge xs' ys 28/81

94 ANONYMOUS FUNCTIONS Anonymous functions are often called λ-expressions. Haskell people think that \ looks close enough to λ. So an anonymous function for additing two elements together would be \x y -> x + y. 29/81

95 ANONYMOUS FUNCTIONS Anonymous functions are often called λ-expressions. Haskell people think that \ looks close enough to λ. So an anonymous function for additing two elements together would be \x y -> x + y. The normal function definition add x y = x + y is just syntactic sugar for add = \x y -> x + y 29/81

96 ANONYMOUS FUNCTIONS Anonymous functions are often called λ-expressions. Haskell people think that \ looks close enough to λ. So an anonymous function for additing two elements together would be \x y -> x + y. The normal function definition add x y = x + y is just syntactic sugar for add = \x y -> x + y or, as we will see soon, for add = \x -> \y -> x + y 29/81

97 COMMON ITERATION PATTERNS (1) Many things we do using loops in imperative languages are instances of some common patterns. Expressing these patterns explicitly instead of hand-crafting them using loops makes our code more readable. 30/81

98 COMMON ITERATION PATTERNS (2) Mapping: Transform a list into a new list by applying a function to every element: map (\x -> 2*x) [1.. 10] == [2, ] 31/81

99 COMMON ITERATION PATTERNS (2) Mapping: Transform a list into a new list by applying a function to every element: map (\x -> 2*x) [1.. 10] == [2, ] Folding: Accumulate the elements of a list into a single value: foldr (\x y -> x + y) 0 [1.. 10] == the sum of the list elements 31/81

100 COMMON ITERATION PATTERNS (2) Mapping: Transform a list into a new list by applying a function to every element: map (\x -> 2*x) [1.. 10] == [2, ] Folding: Accumulate the elements of a list into a single value: foldr (\x y -> x + y) 0 [1.. 10] == the sum of the list elements Filtering: Extract the list elements that meet a given condition: filter odd [1.. 10] == [1, 3, 5, 7, 9] 31/81

101 IMPLEMENTING ITERATION CONSTRUCTS map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs 32/81

102 IMPLEMENTING ITERATION CONSTRUCTS map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs foldr :: (a -> b -> b) -> b -> [a] -> b foldr f b as = go b as where go b [] = b go b (a:as') = f a (go b as') 32/81

103 IMPLEMENTING ITERATION CONSTRUCTS map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs foldr :: (a -> b -> b) -> b -> [a] -> b foldr f b as = go b as where go b [] = b go b (a:as') = f a (go b as') filter :: (t -> Bool) -> [t] -> [t] filter _ [] = [] filter p (x:xs) p x = x : filter p xs otherwise = filter p xs 32/81

104 CURRIED FUNCTIONS AND PARTIAL APPLICATION (1) Flipping all pairs in a list: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map swap xs where swap (a,b) = (b,a) 33/81

105 CURRIED FUNCTIONS AND PARTIAL APPLICATION (1) Flipping all pairs in a list: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map swap xs where swap (a,b) = (b,a) A little less verbose: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map (\(a,b) -> (b,a)) xs 33/81

106 CURRIED FUNCTIONS AND PARTIAL APPLICATION (1) Flipping all pairs in a list: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map swap xs where swap (a,b) = (b,a) A little less verbose: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map (\(a,b) -> (b,a)) xs Highly compressed: swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) 33/81

107 CURRIED FUNCTIONS AND PARTIAL APPLICATION (1) Flipping all pairs in a list: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map swap xs where swap (a,b) = (b,a) A little less verbose: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map (\(a,b) -> (b,a)) xs Highly compressed: swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,))??? 33/81

108 CURRIED FUNCTIONS AND PARTIAL APPLICATION (1) Flipping all pairs in a list: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map swap xs where swap (a,b) = (b,a) A little less verbose: swapelems :: [(a,b)] -> [(b,a)] swapelems xs = map (\(a,b) -> (b,a)) xs Highly compressed: swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) This is (almost) what you d do in practice.??? 33/81

109 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> b -> c -> d. Why not f :: (a, b, c) -> d? 34/81

110 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> b -> c -> d. Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! 34/81

111 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> b -> c -> d. Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is 34/81

112 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> b -> c -> d. Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is a function with one argument of type b and whose result is 34/81

113 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> b -> c -> d. Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is a function with one argument of type b and whose result is a function with one argument of type c and whose result is of type d. 34/81

114 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> (b -> (c -> d)). Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is a function with one argument of type b and whose result is a function with one argument of type c and whose result is of type d. 34/81

115 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> (b -> (c -> d)). Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is a function with one argument of type b and whose result is a function with one argument of type c and whose result is of type d. f :: (a, b, c) -> d has one argument of type (a, b, c) and its result is of type d. 34/81

116 CURRIED FUNCTIONS AND PARTIAL APPLICATION (2) We write a multi-argument function as f :: a -> (b -> (c -> d)). Why not f :: (a, b, c) -> d? They re different, but they have one thing in common: neither is really a multi-argument function! f :: a -> b -> c -> d has one argument of type a and its result is a function with one argument of type b and whose result is a function with one argument of type c and whose result is of type d. f :: (a, b, c) -> d has one argument of type (a, b, c) and its result is of type d. We call f :: a -> b -> c -> d a curried function. 34/81

117 CURRIED FUNCTIONS AND PARTIAL APPLICATION (3) f x y z really means ((f x) y) z, that is, Apply f to x. Apply the resulting function to y. Apply the resulting function to z. And that s the final result which could itself be a function! 35/81

118 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. 36/81

119 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. Without currying: timestwo :: [Int] -> [Int] timestwo xs = map (\x -> 2*x) xs 36/81

120 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. Without currying: timestwo :: [Int] -> [Int] timestwo xs = map (\x -> 2*x) xs With currying (part 1): 36/81

121 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. Without currying: timestwo :: [Int] -> [Int] timestwo xs = map (\x -> 2*x) xs With currying (part 1): (*) is a function of type (*) :: Num t => t -> t -> t. 36/81

122 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. Without currying: timestwo :: [Int] -> [Int] timestwo xs = map (\x -> 2*x) xs With currying (part 1): (*) is a function of type (*) :: Num t => t -> t -> t. It maps its first argument x to a function that multiplies its second argument y by x. 36/81

123 WHY ARE CURRIED FUNCTIONS BETTER? (1) Multiplying all elements in a list by two. Without currying: timestwo :: [Int] -> [Int] timestwo xs = map (\x -> 2*x) xs With currying (part 1): (*) is a function of type (*) :: Num t => t -> t -> t. It maps its first argument x to a function that multiplies its second argument y by x. timestwo xs = map (* 2) xs 36/81

124 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): 37/81

125 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): map is a function of type map :: (a -> b) -> [a] -> [b]. 37/81

126 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): map is a function of type map :: (a -> b) -> [a] -> [b]. It maps its first argument, a function f, to a function m that applies f to every element in its argument list. 37/81

127 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): map is a function of type map :: (a -> b) -> [a] -> [b]. It maps its first argument, a function f, to a function m that applies f to every element in its argument list. timestwo = map (* 2) 37/81

128 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): map is a function of type map :: (a -> b) -> [a] -> [b]. It maps its first argument, a function f, to a function m that applies f to every element in its argument list. timestwo = map (* 2) This is called point-free programming. The focus is on building functions from functions instead of specifying the value of a function for a particular argument. 37/81

129 WHY ARE CURRIED FUNCTIONS BETTER? (2) With currying (part 2): map is a function of type map :: (a -> b) -> [a] -> [b]. It maps its first argument, a function f, to a function m that applies f to every element in its argument list. timestwo = map (* 2) This is called point-free programming. The focus is on building functions from functions instead of specifying the value of a function for a particular argument. Revisiting foldr: foldr :: (a -> b -> b) -> b -> [a] -> b foldr f = go where go b [] = b go b (a:as') = f a (go b as') 37/81

130 FUNCTION COMPOSITION Point-free programming cannot work without function composition: multiplyevens :: [Int] -> [Int] multiplyevens xs = map (* 2) (filter even xs) 38/81

131 FUNCTION COMPOSITION Point-free programming cannot work without function composition: multiplyevens :: [Int] -> [Int] multiplyevens xs = map (* 2) (filter even xs) Function composition: (.) :: (b -> c) -> (a -> b) -> (a -> c) (f. g) x = f (g x) 38/81

132 FUNCTION COMPOSITION Point-free programming cannot work without function composition: multiplyevens :: [Int] -> [Int] multiplyevens xs = map (* 2) (filter even xs) Function composition: (.) :: (b -> c) -> (a -> b) -> (a -> c) (f. g) x = f (g x) multiplyevens = map (* 2). filter even 38/81

133 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x 39/81

134 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments 39/81

135 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair 39/81

136 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair 39/81

137 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair Why the need for a function application operator? 39/81

138 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair Why the need for a function application operator? Function application binds more tightly than function composition, which binds more tightly than (\$): 39/81

139 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair Why the need for a function application operator? Function application binds more tightly than function composition, which binds more tightly than (\$): f :: a -> b g :: b -> c x :: a 39/81

140 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair Why the need for a function application operator? Function application binds more tightly than function composition, which binds more tightly than (\$): f :: a -> b g :: b -> c x :: a g. f \$ x :: c 39/81

141 A FEW USEFUL FUNCTIONS (\$) :: (a -> b) -> a -> b -- f \$ x == f x flip :: (a -> b -> c) -> (b -> a -> c) -- Exchange the first two -- function arguments curry :: ((a,b) -> c) -> (a -> b -> c) -- Curry a function whose -- argument is a pair uncurry :: (a -> b -> c) -> ((a,b) -> c) -- Collapse two function -- arguments into a pair Why the need for a function application operator? Function application binds more tightly than function composition, which binds more tightly than (\$): f :: a -> b g :: b -> c x :: a g. f \$ x :: c g. f x -- error! 39/81

142 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) 40/81

143 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) flip :: (b -> a -> c) -> (a -> b -> c) 40/81

144 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) flip :: (b -> a -> c) -> (a -> b -> c) uncurry :: (a -> b -> c) -> ((a,b) -> c) 40/81

145 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) flip :: (b -> a -> c) -> (a -> b -> c) uncurry :: (a -> b -> c) -> ((a,b) -> c) uncurry. flip :: (b -> a -> c) -> ((a,b) -> c) 40/81

146 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) flip :: (b -> a -> c) -> (a -> b -> c) uncurry :: (a -> b -> c) -> ((a,b) -> c) uncurry. flip :: (b -> a -> c) -> ((a,b) -> c) (,) :: b -> a -> (b,a) 40/81

147 BACK TO SWAPELEMS swapelems :: [(a,b)] -> [(b,a)] swapelems = map (uncurry. flip \$ (,)) flip :: (b -> a -> c) -> (a -> b -> c) uncurry :: (a -> b -> c) -> ((a,b) -> c) uncurry. flip :: (b -> a -> c) -> ((a,b) -> c) (,) :: b -> a -> (b,a) uncurry. flip \$ (,) :: (a,b) -> (b,a) 40/81

148 DEFINING AND USING TYPE CLASSES Sequences: Containers that can be flattened to a list: class Sequence s where flatten :: s t -> [t] flatmap :: (a -> b) -> s a -> [b] flatmap f = map f. flatten 41/81

149 DEFINING AND USING TYPE CLASSES Sequences: Containers that can be flattened to a list: class Sequence s where flatten :: s t -> [t] flatmap :: (a -> b) -> s a -> [b] flatmap f = map f. flatten generalizedfilter :: Sequence s => (t -> Bool) -> s t -> [t] generalizedfilter p = filter p. flatten 41/81

150 DEFINING INSTANCES OF TYPE CLASSES Lists are sequences: instance Sequence [] where flatten = id flatmap = map 42/81

151 DEFINING INSTANCES OF TYPE CLASSES Lists are sequences: instance Sequence [] where flatten = id flatmap = map So are arrays: instance Sequence (Array ix) where flatten = elems 42/81

152 DEFINING INSTANCES OF TYPE CLASSES Lists are sequences: instance Sequence [] where flatten = id flatmap = map So are arrays: instance Sequence (Array ix) where flatten = elems and binary trees: instance Sequence Tree where flatten Leaf = [] flatten (Tree x l r) = flatten l ++ [x] ++ flatten r 42/81

153 MAYBE: A SAFER NULL Maybe t can be used as the result of functions that may fail: lookup :: Eq a => a -> [(a,b)] -> Maybe b 43/81

154 MAYBE: A SAFER NULL Maybe t can be used as the result of functions that may fail: lookup :: Eq a => a -> [(a,b)] -> Maybe b data Maybe t = Just t Nothing 43/81

155 WORKING WITH MAYBE Using patterns: formattedlookup :: (Eq a, Show a, Show b) => a -> [(a,b)] -> String formattedlookup x ys = format (lookup x ys) where format Nothing = "Key " ++ show x ++ " not found" format (Just y) = "Key " ++ show x ++ " stores value " ++ show y 44/81

156 WORKING WITH MAYBE Using patterns: formattedlookup :: (Eq a, Show a, Show b) => a -> [(a,b)] -> String formattedlookup x ys = format (lookup x ys) where format Nothing = "Key " ++ show x ++ " not found" format (Just y) = "Key " ++ show x ++ " stores value " ++ show y Using maybe: maybe :: b -> (a -> b) -> Maybe a -> b maybe def _ Nothing = def maybe _ f (Just x) = f x 44/81

157 WORKING WITH MAYBE Using patterns: formattedlookup :: (Eq a, Show a, Show b) => a -> [(a,b)] -> String formattedlookup x ys = format (lookup x ys) where format Nothing = "Key " ++ show x ++ " not found" format (Just y) = "Key " ++ show x ++ " stores value " ++ show y Using maybe: maybe :: b -> (a -> b) -> Maybe a -> b maybe def _ Nothing = def maybe _ f (Just x) = f x lookupwithdefault :: Eq a => a -> b -> [(a,b)] -> b lookupwithdefault x y ys = maybe y id (lookup x ys) 44/81

158 EITHER: CAPTURING DIFFERENT OUTCOMES Either a b can be used as the result of computations that may produce two different outcomes: data Either a b = Left a Right b tagevensandodds :: [Int] -> [Either Int Int] tagevensandodds = map tag where tag x even x = Left x otherwise = Right x 45/81

159 WORKING WITH EITHER Using patterns: addormultiply :: [Int] -> [Int] addormultiply = map aom. tagevensandodds where aom (Left even) = even + 2 aom (Right odd) = 2 * odd 46/81

160 WORKING WITH EITHER Using patterns: addormultiply :: [Int] -> [Int] addormultiply = map aom. tagevensandodds where aom (Left even) = even + 2 aom (Right odd) = 2 * odd Using either: either :: (a -> c) -> (b -> c) -> Either a b -> c either f _ (Left x) = f x either _ g (Right y) = g y addormultiply = map (either (+ 2) (* 2)). tagevensandodds 46/81

161 FUNCTORS: AN ABSTRACTION FOR CONTAINERS map allows us to apply a function to every list element, but we cannot map over the elements of a binary tree. 47/81

162 FUNCTORS: AN ABSTRACTION FOR CONTAINERS map allows us to apply a function to every list element, but we cannot map over the elements of a binary tree. What if I want to apply a function to Maybe some value? 47/81

163 FUNCTORS: AN ABSTRACTION FOR CONTAINERS map allows us to apply a function to every list element, but we cannot map over the elements of a binary tree. What if I want to apply a function to Maybe some value? The Functor type class captures containers: class Functor f where fmap :: (a -> b) -> f a -> f b 47/81

164 EXAMPLES OF FUNCTORS The list type is a functor: instance Functor [] where fmap = map 48/81

165 EXAMPLES OF FUNCTORS The list type is a functor: instance Functor [] where fmap = map So is Maybe: instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just x) = Just (f x) 48/81

166 EXAMPLES OF FUNCTORS The list type is a functor: instance Functor [] where fmap = map So is Maybe: instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just x) = Just (f x) and the binary tree type: instance Functor Tree where fmap _ Leaf = Leaf fmap f (Tree x l r) = Tree (f x) (fmap f l) (fmap f r) 48/81

167 LAZY EVALUATION What takes longer? let l1 = [1.. 10] let l2 = [ ] let l3 = [1..] 49/81

168 LAZY EVALUATION What takes longer? let l1 = [1.. 10] let l2 = [ ] let l3 = [1..] They all take constant time! 49/81

169 LAZY EVALUATION What takes longer? let l1 = [1.. 10] let l2 = [ ] let l3 = [1..] They all take constant time! Haskell evaluates expressions lazily: Expressions are evaluated only when their value is needed. The evaluated value is cached, in case it s needed again. 49/81

170 LAZY EVALUATION What takes longer? let l1 = [1.. 10] let l2 = [ ] let l3 = [1..] They all take constant time! Haskell evaluates expressions lazily: Expressions are evaluated only when their value is needed. The evaluated value is cached, in case it s needed again. head l1 produces 1 and changes the representation of l1 to 1 : [2.. 10]. 49/81

171 LAZY EVALUATION What takes longer? let l1 = [1.. 10] let l2 = [ ] let l3 = [1..] They all take constant time! Haskell evaluates expressions lazily: Expressions are evaluated only when their value is needed. The evaluated value is cached, in case it s needed again. head l1 produces 1 and changes the representation of l1 to 1 : [2.. 10]. Useful consequence: We can define infinite data structures as long as we only work with finite portions of them. 49/81

172 WHY ARE INFINITE DATA STRUCTURES USEFUL? (1) 50/81

173 WHY ARE INFINITE DATA STRUCTURES USEFUL? (1) Elegance! 50/81

174 WHY ARE INFINITE DATA STRUCTURES USEFUL? (1) Elegance! Assume we write a parser and want to provide line numbers in our error messages. We need to annotate each input line with its number. 50/81

175 WHY ARE INFINITE DATA STRUCTURES USEFUL? (1) Elegance! Assume we write a parser and want to provide line numbers in our error messages. We need to annotate each input line with its number. The hard way: splitinput :: String -> [(Int, String)] splitinput text = zip ns ls where ls = lines text ns = [1.. length ls] 50/81

176 WHY ARE INFINITE DATA STRUCTURES USEFUL? (1) Elegance! Assume we write a parser and want to provide line numbers in our error messages. We need to annotate each input line with its number. The hard way: splitinput :: String -> [(Int, String)] splitinput text = zip ns ls where ls = lines text ns = [1.. length ls] The easy way: splitinput :: String -> [(Int, String)] splitinput = zip [1..]. lines 50/81

177 WHY ARE INFINITE DATA STRUCTURES USEFUL? (2) The inifinite sequence of Fibonacci numbers: fibonacci :: [Int] fibonacci = 1 : 1 : zipwith (+) fibonacci (tail fibonacci) 51/81

178 WHY ARE INFINITE DATA STRUCTURES USEFUL? (2) The inifinite sequence of Fibonacci numbers: fibonacci :: [Int] fibonacci = 1 : 1 : zipwith (+) fibonacci (tail fibonacci) The first 10 Fibonacci numbers: take 10 fibonacci == [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] 51/81

179 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (1) BFS numbering of a binary tree /81

180 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (1) BFS numbering of a binary tree The naive solution: Build a list of nodes in level order Number the nodes Reassemble the tree I refuse to turn this into code; it s messy /81

181 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (2) bfs' :: ([Int], Tree t) -> ([Int], Tree Int) bfs' (nums, Leaf) = (nums, Leaf) bfs' (num:nums, Tree _ l r) = (num+1 : nums'', Tree num l' r') where (nums', l') = bfs' (nums, l) (nums'', r') = bfs' (nums', r) x 1 x x 1 x 2 x 2 x x x 3 x 3 x x x x 4 x x 4 x 5 x 5 x x /81

182 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (3) /81

183 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (3) /81

184 MORE LAZINESS: USING VALUES BEFORE THEY RE COMPUTED (3) bfs :: Tree t -> Tree Int bfs t = t' where (nums, t') = bfs' (1 : nums, t) /81

185 LISTS AS CONTROL STRUCTURES (1) Many computations are about transforming collections of items. 55/81

186 LISTS AS CONTROL STRUCTURES (1) Many computations are about transforming collections of items. It would be clearest to express such sequences of transformations explicitly, but explictly building up these collections (vectors, lists, ) is often costly. 55/81

187 LISTS AS CONTROL STRUCTURES (1) Many computations are about transforming collections of items. It would be clearest to express such sequences of transformations explicitly, but explictly building up these collections (vectors, lists, ) is often costly. We often build up complicated loops to avoid materializing intermediate collections. 55/81

188 LISTS AS CONTROL STRUCTURES (1) Many computations are about transforming collections of items. It would be clearest to express such sequences of transformations explicitly, but explictly building up these collections (vectors, lists, ) is often costly. We often build up complicated loops to avoid materializing intermediate collections. Laziness allows us to express computations as list transformations while still not materializing any intermediate lists. 55/81

189 LISTS AS CONTROL STRUCTURES (2) filterandmultiply :: [Bool] -> [Int] -> [Int] -> [Int] filterandmultiply keep items factors = map (*) kept factors where kept = map snd keptpairs keptpairs = filter fst pairs pairs = zip keep items 56/81

190 LISTS AS CONTROL STRUCTURES (2) filterandmultiply :: [Bool] -> [Int] -> [Int] -> [Int] filterandmultiply keep items factors = map (*) kept factors where kept = map snd keptpairs keptpairs = filter fst pairs pairs = zip keep items keep items zip pairs filter fst keptpairs map snd kept factors map (*) 56/81

191 LISTS AS CONTROL STRUCTURES (2) filterandmultiply :: [Bool] -> [Int] -> [Int] -> [Int] filterandmultiply keep items factors = map (*) kept factors where kept = map snd keptpairs keptpairs = filter fst pairs pairs = zip keep items keep items zip pairs filter fst keptpairs map snd kept factors map (*) Only one node of each list needed at any point in time. A good compiler will optimize the lists away. 56/81

192 SOME PITFALLS OF LAZINESS (1) Three kinds of folds: 57/81

193 SOME PITFALLS OF LAZINESS (1) Three kinds of folds: Right to left: foldr :: (a -> b -> b) -> b -> [a] -> b foldr f = go where go b [] = b go b (x:xs) = f x (go b xs) 57/81

194 SOME PITFALLS OF LAZINESS (1) Three kinds of folds: Right to left: Left to right, lazy: foldr :: (a -> b -> b) -> b -> [a] -> b foldr f = go where go b [] = b go b (x:xs) = f x (go b xs) foldl :: (a -> b -> a) -> a -> [b] -> a foldl f = go where go a [] = a go a (x:xs) = go (f a x) xs 57/81

### Lecture 4: Higher Order Functions

Lecture 4: Higher Order Functions Søren Haagerup Department of Mathematics and Computer Science University of Southern Denmark, Odense September 26, 2017 HIGHER ORDER FUNCTIONS The order of a function

### Shell CSCE 314 TAMU. Functions continued

1 CSCE 314: Programming Languages Dr. Dylan Shell Functions continued 2 Outline Defining Functions List Comprehensions Recursion 3 A Function without Recursion Many functions can naturally be defined in

### PROGRAMMING IN HASKELL. Chapter 2 - First Steps

PROGRAMMING IN HASKELL Chapter 2 - First Steps 0 The Hugs System Hugs is an implementation of Haskell 98, and is the most widely used Haskell system; The interactive nature of Hugs makes it well suited

### Programming Languages Fall 2013

Programming Languages Fall 2013 Lecture 2: types Prof. Liang Huang huang@qc.cs.cuny.edu Recap of Lecture 1 functional programming vs. imperative programming basic Haskell syntax function definition lazy

### A tour of the Haskell Prelude

A tour of the Haskell Prelude Bernie Pope 2001 1 Haskell The Haskell language was conceived during a meeting held at the 1987 Functional Programming and Computer Architecture conference (FPCA 87). At the

### Programming with Math and Logic

.. Programming with Math and Logic an invitation to functional programming Ed Morehouse Wesleyan University The Plan why fp? terms types interfaces The What and Why of Functional Programming Computing

### Functional Programming TDA 452, DIT 142

Chalmers Göteborgs Universitet 2018-01-11 Examiner: Thomas Hallgren, D&IT, Answering questions at approx 15.00 (or by phone) Functional Programming TDA 452, DIT 142 2018-01-11 14.00 18.00 Samhällsbyggnad

### CS 457/557: Functional Languages

CS 457/557: Functional Languages From Trees to Type Classes Mark P Jones Portland State University 1 Trees:! " There are many kinds of tree data structure.! " For example: data BinTree a = Leaf a BinTree

### Lecture 2: List algorithms using recursion and list comprehensions

Lecture 2: List algorithms using recursion and list comprehensions Søren Haagerup Department of Mathematics and Computer Science University of Southern Denmark, Odense September 12, 2017 Expressions, patterns

### CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

CSC312 Principles of Programming Languages : Functional Programming Language Overview of Functional Languages They emerged in the 1960 s with Lisp Functional programming mirrors mathematical functions:

### Introduction to Functional Programming in Haskell 1 / 56

Introduction to Functional Programming in Haskell 1 / 56 Outline Why learn functional programming? The essence of functional programming What is a function? Equational reasoning First-order vs. higher-order

Overloading, Type Classes, and Algebraic Datatypes Delivered by Michael Pellauer Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. September 28, 2006 September 28, 2006 http://www.csg.csail.mit.edu/6.827

### According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

Lecture 7: Haskell CSC 131 Fall, 2014 Kim Bruce According to Larry Wall (designer of PERL): a language by geniuses for geniuses He s wrong at least about the latter part though you might agree when we

### User-Defined Algebraic Data Types

72 Static Semantics User-Defined Types User-Defined Algebraic Data Types An algebraic data type declaration has the general form: data cx T α 1... α k = K 1 τ 11... τ 1k1... K n τ n1... τ nkn introduces

Advanced features of Functional Programming (Haskell) Polymorphism and overloading January 10, 2017 Monomorphic and polymorphic types A (data) type specifies a set of values. Examples: Bool: the type of

### Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

CMSC 330: Organization of Programming Languages OCaml 2 Higher Order Functions Tuples Constructed using (e1,..., en) Deconstructed using pattern matching Patterns involve parens and commas, e.g., (p1,p2,

### Continuation Passing Style. Continuation Passing Style

161 162 Agenda functional programming recap problem: regular expression matcher continuation passing style (CPS) movie regular expression matcher based on CPS correctness proof, verification change of

CSci 450: Org. of Programming Languages Overloading and Type Classes H. Conrad Cunningham 27 October 2017 (after class) Contents 9 Overloading and Type Classes 1 9.1 Chapter Introduction.........................

### Type system. Type theory. Haskell type system. EDAN40: Functional Programming Types and Type Classes (revisited)

Type system EDAN40: Functional Programming Types and Type Classes (revisited) Jacek Malec Dept. of Computer Science, Lund University, Sweden April 3rd, 2017 In programming languages, a type system is a

### An Overview of Miranda

FROM SIGPLAN NOTICES, 21(12):158-166, December 1986. c D.A.Turner An Overview of Miranda David Turner Computing Laboratory University of Kent Canterbury CT2 7NF ENGLAND Miranda is an advanced functional

### Topic 5: Higher Order Functions

Topic 5: Higher Order Functions 1 Recommended Exercises and Readings From Haskell: The craft of functional programming (3 rd Ed.) Exercises: 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 10.10,

### CS 360: Programming Languages Lecture 12: More Haskell

CS 360: Programming Languages Lecture 12: More Haskell Geoffrey Mainland Drexel University Adapted from Brent Yorgey s course Introduction to Haskell. Section 1 Administrivia Administrivia Homework 5 due

### Homework 1: Functional Programming, Haskell

Com S 541 Programming Languages 1 September 25, 2005 Homework 1: Functional Programming, Haskell Due: problems 1 and 3, Thursday, September 1, 2005; problems 4-9, Thursday, September 15, 2005; remaining

### Parallel Haskell on MultiCores and Clusters

Parallel Haskell on MultiCores and Clusters (part of Advanced Development Techniques) Hans-Wolfgang Loidl School of Mathematical and Computer Sciences Heriot-Watt University, Edinburgh (presented at the

### Abstract Types, Algebraic Types, and Type Classes

Informatics 1 Functional Programming Lectures 13 and 14 Monday 9 and Tuesday 10 November 2009 Abstract Types, Algebraic Types, and Type Classes Philip Wadler University of Edinburgh Reminders Tutorial

### Principles of Programming Languages, 3

Principles of Programming Languages, 3 Matteo Pradella May 2015 Matteo Pradella Principles of Programming Languages, 3 May 2015 1 / 94 1 Introduction on purity and evaluation 2 Haskell Matteo Pradella

### An Introduction to Programming in Haskell. Gabriel J. Ferrer Hendrix College

An Introduction to Programming in Haskell Gabriel J. Ferrer Hendrix College Overview Functional programming Property testing Iteration Type system I/O Installation Go to: http://www.haskell.org/ Download

### CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

1/43 CSc 372 Comparative Programming Languages 8 : Haskell Function Examples Department of Computer Science University of Arizona collberg@gmail.com Copyright c 2013 Christian Collberg Functions over Lists

### Data types for mcrl2

Data types for mcrl2 Aad Mathijssen April 5, 2018 We provide a syntax for the standard data types of the mcrl2 language. This syntax is intended to be a practical mix between standard mathematical notation

### Thoughts on Assignment 4 Haskell: Flow of Control

Thoughts on Assignment 4 Haskell: Flow of Control CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, February 27, 2017 Glenn G. Chappell Department of Computer

### Haskell-Tutorial. Damir Medak Gerhard Navratil. Institute for Geoinformation Technical University Vienna. February 2003

Haskell-Tutorial Damir Medak Gerhard Navratil Institute for Geoinformation Technical University Vienna February 2003 There are numerous books on functional programming. These books are good, but usually

### Tentamen Functioneel Programmeren 2001 Informatica, Universiteit Utrecht Docent: Wishnu Prasetya

Tentamen Functioneel Programmeren 2001 Informatica, Universiteit Utrecht Docent: Wishnu Prasetya 04-05-2001, 09.00-12.00, Educatorium Gamma This test consists of two parts. For the first part, which is

### # true;; - : bool = true. # false;; - : bool = false 9/10/ // = {s (5, "hi", 3.2), c 4, a 1, b 5} 9/10/2017 4

Booleans (aka Truth Values) Programming Languages and Compilers (CS 421) Sasa Misailovic 4110 SC, UIUC https://courses.engr.illinois.edu/cs421/fa2017/cs421a # true;; - : bool = true # false;; - : bool

### Tree Oriented Programming. Jeroen Fokker

Tree Oriented Programming Jeroen Fokker Tree oriented programming Many problems are like: Input text transform process unparse Output text Tree oriented programming Many problems are like: Input text parse

### An introduction to C++ template programming

An introduction to C++ template programming Hayo Thielecke University of Birmingham http://www.cs.bham.ac.uk/~hxt March 2015 Templates and parametric polymorphism Template parameters Member functions of

### General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

General Computer Science (CH08-320101) Fall 2016 SML Tutorial: Practice Problems November 30, 2016 Abstract This document accompanies the traditional SML tutorial in GenCS. It contains a sequence of simple

### Types in Programming Languages Dynamic and Static Typing, Type Inference (CTM 2.8.3, EPL* 4) Abstract Data Types (CTM 3.7) Monads (GIH** 9)

Types in Programming Languages Dynamic and Static Typing, Type Inference (CTM 2.8.3, EPL* 4) Abstract Data Types (CTM 3.7) Monads (GIH** 9) Carlos Varela Rensselaer Polytechnic Institute September 23,

### Monad Background (3A) Young Won Lim 11/18/17

Copyright (c) 2016-2017 Young W. Lim. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published

### GHCi: Getting started (1A) Young Won Lim 6/3/17

GHCi: Getting started (1A) Copyright (c) 2016-2017 Young W. Lim. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2

### Option Values, Arrays, Sequences, and Lazy Evaluation

Option Values, Arrays, Sequences, and Lazy Evaluation Björn Lisper School of Innovation, Design, and Engineering Mälardalen University bjorn.lisper@mdh.se http://www.idt.mdh.se/ blr/ Option Values, Arrays,

### CSE 307: Principles of Programming Languages

CSE 307: Principles of Programming Languages Syntax R. Sekar 1 / 63 Topics 1. Introduction 2. Basics 3. Functions 4. Data Structures 5. Overview 6. OCAML Performance 2 / 63 Section 1 Introduction 3 / 63

### CSci 4223 Principles of Programming Languages

CSci 4223 Principles of Programming Languages Lecture 11 Review Features learned: functions, tuples, lists, let expressions, options, records, datatypes, case expressions, type synonyms, pattern matching,

### Lists. Michael P. Fourman. February 2, 2010

Lists Michael P. Fourman February 2, 2010 1 Introduction The list is a fundamental datatype in most functional languages. ML is no exception; list is a built-in ML type constructor. However, to introduce

### Haskell: yet another Functional Language. Distributed and Parallel Technology

Distributed and Parallel Technology Introducing Haskell Hans-Wolfgang Loidl http://www.macs.hw.ac.uk/~hwloidl School of Mathematical and Computer Sciences Heriot-Watt University, Edinburgh Haskell: yet

### Functions and Recursion. Dr. Philip Cannata 1

Functions and Recursion Dr. Philip Cannata 1 10 High Level Languages This Course Java (Object Oriented) Jython in Java Relation ASP RDF (Horn Clause Deduction, Semantic Web) Dr. Philip Cannata 2 let transformation,

### The Art of Recursion: Problem Set 10

The Art of Recursion: Problem Set Due Tuesday, November Tail recursion A recursive function is tail recursive if every recursive call is in tail position that is, the result of the recursive call is immediately

### Monads seen so far: IO vs Gen

Monads David Sands Monads seen so far: IO vs Gen IO A Gen A Instructions to build a value of type A by interacting with the operating system Instructions to create a random value of type A Run by the ghc

### Data Types. (with Examples In Haskell) COMP 524: Programming Languages Srinivas Krishnan March 22, 2011

Data Types (with Examples In Haskell) COMP 524: Programming Languages Srinivas Krishnan March 22, 2011 Based in part on slides and notes by Bjoern 1 Brandenburg, S. Olivier and A. Block. 1 Data Types Hardware-level:

### G Programming Languages - Fall 2012

G22.2110-003 Programming Languages - Fall 2012 Lecture 10 Thomas Wies New York University Review Last class ML Outline Modules Sources: PLP, 3.3.4, 3.3.5, 3.8 McConnell, Steve. Code Complete, Second Edition,

### Accurate Step Counting

Accurate Step Counting Catherine Hope and Graham Hutton School of Computer Science and IT University of Nottingham, UK {cvh,gmh}@cs.nott.ac.uk Abstract Starting with an evaluator for a language, an abstract

Functional Programming Language Haskell Mohammed Aslam CIS 24 Prof. Kopec Presentation: 03 Date: 05/05/2003 Haskell is a general purpose, purely functional programming language named after the logician

### Informatics 1 Functional Programming Lecture 12. Data Abstraction. Don Sannella University of Edinburgh

Informatics 1 Functional Programming Lecture 12 Data Abstraction Don Sannella University of Edinburgh Part I Sets as lists without abstraction We will look again at our four ways of implementing sets.

### Short Notes of CS201

#includes: Short Notes of CS201 The #include directive instructs the preprocessor to read and include a file into a source code file. The file name is typically enclosed with < and > if the file is a system

### INFOB3TC Solutions for the Exam

Department of Information and Computing Sciences Utrecht University INFOB3TC Solutions for the Exam Johan Jeuring Monday, 13 December 2010, 10:30 13:00 lease keep in mind that often, there are many possible

### Polymorphism Overview (1A) Young Won Lim 2/20/18

Polymorphism Overview (1A) Copyright (c) 2016-2017 Young W. Lim. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2

### Conversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";

Lecture #23: Conversion and Type Inference Administrivia. Due date for Project #2 moved to midnight tonight. Midterm mean 20, median 21 (my expectation: 17.5). In Java, this is legal: Object x = "Hello";

### CSCI-GA Final Exam

CSCI-GA 2110-003 - Final Exam Instructor: Thomas Wies Name: Sample Solution ID: You have 110 minutes time. There are 7 assignments and you can reach 110 points in total. You can solve the exercises directly

### CIS 194: Homework 4. Due Wednesday, February 18, What is a Number?

CIS 194: Homework 4 Due Wednesday, February 18, 2015 What is a Number? This may sound like a deep, philosophical question, but the Haskell type system gives us a simple way to answer it. A number is any

### CIS 194: Homework 6. Due Wednesday, 4 March. Fibonacci numbers. It s all about being lazy.

CIS 194: Homework 6 Due Wednesday, 4 March It s all about being lazy. Fibonacci numbers The Fibonacci numbers F n are defined as the sequence of integers, beginning with 1 and 1, where every integer in

About the Tutorial Haskell is a widely used purely functional language. Functional programming is based on mathematical functions. Besides Haskell, some of the other popular languages that follow Functional

### Week 5 Tutorial Structural Induction

Department of Computer Science, Australian National University COMP2600 / COMP6260 Formal Methods in Software Engineering Semester 2, 2016 Week 5 Tutorial Structural Induction You should hand in attempts

### Time and space behaviour. Chapter 20

Time and space behaviour Chapter 20 Algorithmic complexity How many steps does it take to execute an algorithm given an input of size n? Complexity of functions Consider: f n = 2 n 2 + 4 n + 13 This function

### Scheme as implemented by Racket

Scheme as implemented by Racket (Simple view:) Racket is a version of Scheme. (Full view:) Racket is a platform for implementing and using many languages, and Scheme is one of those that come out of the

Processadors de Llenguatge II Functional Paradigm II Pratt A.7 Robert Harper s SML tutorial (Sec II) Rafael Ramirez Dep Tecnologia Universitat Pompeu Fabra User-Defined Types How to define the new type.

T O Y H Advances in Programming Languages APL8: Multiparameter Type Classes, Constructor Classes Ian Stark School of Informatics The University of Edinburgh Thursday 4 February Semester 2 Week 4 E H U

CIS552: Advanced Programming Handout 8 What is a Parser? A parser is a program that analyzes a piece of text to deine its structure (and, typically, returns a tree representing this structure). The World

### CS321 Languages and Compiler Design I Winter 2012 Lecture 13

STATIC SEMANTICS Static Semantics are those aspects of a program s meaning that can be studied at at compile time (i.e., without running the program). Contrasts with Dynamic Semantics, which describe how

### CS558 Programming Languages

CS558 Programming Languages Fall 2016 Lecture 4a Andrew Tolmach Portland State University 1994-2016 Pragmatics of Large Values Real machines are very efficient at handling word-size chunks of data (e.g.

### Documentation for the Idris Language. Version 1.0

Documentation for the Idris Language Version 1.0 Contents 1 The Idris Tutorial 2 2 Frequently Asked Questions 62 3 Implementing State-aware Systems in Idris: The ST Tutorial 67 4 The Effects Tutorial 102

### Documentation for the Idris Language. Version 0.99

Documentation for the Idris Language Version 0.99 Contents 1 The Idris Tutorial 2 2 Frequently Asked Questions 61 3 The Effects Tutorial 66 4 Theorem Proving 98 5 Language Reference 109 6 Tutorials on

### Data Types The ML Type System

7 Data Types 7.2.4 The ML Type System The following is an ML version of the tail-recursive Fibonacci function introduced Fibonacci function in ML in Section 6.6.1: EXAMPLE 7.96 1. fun fib (n) = 2. let

### List Processing in Ocaml

CS251 Programming Languages Handout # 14 Prof. Lyn Turbak February 2, 2007 Wellesley College List Processing in Ocaml Given a list of integers ns, suppose we want to return a new list of the same length

### 22c:111 Programming Language Concepts. Fall Types I

22c:111 Programming Language Concepts Fall 2008 Types I Copyright 2007-08, The McGraw-Hill Company and Cesare Tinelli. These notes were originally developed by Allen Tucker, Robert Noonan and modified

### G Programming Languages Spring 2010 Lecture 8. Robert Grimm, New York University

G22.2110-001 Programming Languages Spring 2010 Lecture 8 Robert Grimm, New York University 1 Review Last time Types Fun with O Caml 2 Outline Modules Sources: PLP, 3.3.4, 3.3.5, 3.7 Barrett. Lecture notes,

### Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

Scheme Textbook, Sections 13.1 13.3, 13.7 1 Functional Programming Based on mathematical functions Take argument, return value Only function call, no assignment Functions are first-class values E.g., functions

### Organization of Programming Languages CS3200/5200N. Lecture 11

Organization of Programming Languages CS3200/5200N Razvan C. Bunescu School of Electrical Engineering and Computer Science bunescu@ohio.edu Functional vs. Imperative The design of the imperative languages

### CS Lecture 5: Pattern Matching. Prof. Clarkson Fall Today s music: Puff, the Magic Dragon by Peter, Paul & Mary

CS 3110 Lecture 5: Pattern Matching Prof. Clarkson Fall 2014 Today s music: Puff, the Magic Dragon by Peter, Paul & Mary Review Features so far: variables, operators, let expressions, if expressions, functions

### Haskell Making Our Own Types and Typeclasses

Haskell Making Our Own Types and Typeclasses http://igm.univ-mlv.fr/~vialette/?section=teaching Stéphane Vialette LIGM, Université Paris-Est Marne-la-Vallée January 13, 2015 Making Our Own Types and Typeclasses

### Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction Readings: HtDP, sections 19-24. Language level: Intermediate Student With Lambda different order used in lecture section 24 material introduced much earlier sections 22, 23 not covered

### Polymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy

06-02552 Princ. of Progr. Languages (and Extended ) The University of Birmingham Spring Semester 2016-17 School of Computer Science c Uday Reddy2016-17 Handout 6: Polymorphic Type Systems 1. Polymorphic

### MODELING PROBABILITY IN HASKELL PROGRAMMING LANGUAGE

MODELING PROBABILITY IN HASKELL PROGRAMMING LANGUAGE ONDREJ ŠUCH Abstract. In this note we provide examples how to model work with probability spaces in Haskell programming language. The textbook Concrete

### CSE 130: Programming Languages. Polymorphism. Ranjit Jhala UC San Diego

CSE 130: Programming Languages Polymorphism Ranjit Jhala UC San Diego Q: What is the value of res? let f g = let x = 0 in g 2 let x = 100 let h y = x + y let res = f h (a) 0 (b) 2 (c) 100 (d) 102 (e) 12

### 1 Tutorial 1: The simplest case.

1 Tutorial 1: The simplest case. This is the simplest example of using the GenCheck framework to test an implementation against a specification. This module contains a revlist (reverse) function that reverses

### What is recursion? Recursion. Recursive message() modified. How can a function call itself? contains a reference to itself. Week 10. Gaddis:

Recursion What is recursion? Week 10 Gaddis:19.1-19.5 CS 5301 Spring 2017 Jill Seaman 1 l Generally, when something contains a reference to itself l Math: defining a function in terms of itself l Computer

### CSE 130 [Winter 2014] Programming Languages

CSE 130 [Winter 2014] Programming Languages Higher-Order Functions! Ravi Chugh! Jan 23 Today s Plan A little more practice with recursion Base Pattern Base Expression Induction Pattern Induction Expression

### Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals

Review CS152: Programming Languages Lecture 11 STLC Extensions and Related Topics e ::= λx. e x ee c v ::= λx. e c (λx. e) v e[v/x] e 1 e 2 e 1 e 2 τ ::= int τ τ Γ ::= Γ,x : τ e 2 e 2 ve 2 ve 2 e[e /x]:

### CSE 230 Intermediate Programming in C and C++ Recursion

CSE 230 Intermediate Programming in C and C++ Recursion Fall 2017 Stony Brook University Instructor: Shebuti Rayana What is recursion? Sometimes, the best way to solve a problem is by solving a smaller

### Procedural programming with C

Procedural programming with C Dr. C. Constantinides Department of Computer Science and Software Engineering Concordia University Montreal, Canada August 11, 2016 1 / 77 Functions Similarly to its mathematical

### Tokens, Expressions and Control Structures

3 Tokens, Expressions and Control Structures Tokens Keywords Identifiers Data types User-defined types Derived types Symbolic constants Declaration of variables Initialization Reference variables Type

### Scala : an LLVM-targeted Scala compiler

Scala : an LLVM-targeted Scala compiler Da Liu, UNI: dl2997 Contents 1 Background 1 2 Introduction 1 3 Project Design 1 4 Language Prototype Features 2 4.1 Language Features........................................

### Recursion Chapter 8. What is recursion? How can a function call itself? How can a function call itself? contains a reference to itself.

Recursion Chapter 8 CS 3358 Summer II 2013 Jill Seaman What is recursion?! Generally, when something contains a reference to itself! Math: defining a function in terms of itself! Computer science: when

### Recursion defining an object (or function, algorithm, etc.) in terms of itself. Recursion can be used to define sequences

Section 5.3 1 Recursion 2 Recursion Recursion defining an object (or function, algorithm, etc.) in terms of itself. Recursion can be used to define sequences Previously sequences were defined using a specific

### News and information! Review: Java Programs! Feedback after Lecture 2! Dead-lines for the first two lab assignment have been posted.!

True object-oriented programming: Dynamic Objects Reference Variables D0010E Object-Oriented Programming and Design Lecture 3 Static Object-Oriented Programming UML" knows-about Eckel: 30-31, 41-46, 107-111,

### 6. Pointers, Structs, and Arrays. 1. Juli 2011

1. Juli 2011 Einführung in die Programmierung Introduction to C/C++, Tobias Weinzierl page 1 of 50 Outline Recapitulation Pointers Dynamic Memory Allocation Structs Arrays Bubble Sort Strings Einführung

### Functions and Recursion

Programming Languages Functions and Recursion Dr. Philip Cannata 1 10 High Level Languages This Course Jython in Java Java (Object Oriented) ACL2 (Propositional Induction) Relation Algorithmic Information

### Introduction to Concepts in Functional Programming. CS16: Introduction to Data Structures & Algorithms Spring 2017

Introduction to Concepts in Functional Programming CS16: Introduction to Data Structures & Algorithms Spring 2017 Outline Functions State Functions as building blocks Higher order functions Map Reduce

Debugging in Haskell Lasse Folger June 29, 2016 Abstract In this paper we will give an overview on techniques to debug Haskell programs. At first the problems are presented which occur, when debugging