FP 2005 1.1 3

Functional Programming

WOLFRAM KAHL

[email protected]

Department of Computing and Software McMaster University FP 2005 1.2 4 What Kinds of Programming Languages are There?

Imperative — “telling the machine what to do” Declarative — “telling the machine what to achieve”

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP ++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.3 5 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.4 6 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.5 7 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.6 8 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.7 9 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.8 10 What Kinds of Programming Languages are There?

Imperative Ð ªtelling the machine what to doº Declarative Ð ªtelling the machine what to achieveº

Programming Languages

Imperative Declarative

C, Pascal Functional Logic FORTRAN Object-oriented COBOL Modula-2 Haskell, OCaml Prolog ML, Scheme, LISP C++, Oberon-2 Mercury Java, Smalltalk FP 2005 1.9 11 Paradigms

Imperative Programming Languages Statement oriented languages Every statement changes the machine state Object-oriented languages Organising the state into objects with individual state and behaviour Message passing paradigm (instead of subprogram call) Rule-Based (Logical) Programming Languages Specify rule that specifies problem solution (Prolog, BNF Parsing) Other examples: Decision procedures, Grammar rules (BNF) Programming consists of specifying the attributes of the answer Functional (Applicative) Programming Languages Goal is to understand the function that produces the answer Function composition is major operation Programming consists of building the function that computes the answer FP 2005 1.10 12 Historical Development of Programming Languages FP 2005 1.11 13 Historical Development of Programming Languages

Emphasis has changed: FP 2005 1.12 14 Historical Development of Programming Languages

Emphasis has changed:

– from making life easier for the computer FP 2005 1.13 15 Historical Development of Programming Languages

Emphasis has changed:

– from making life easier for the computer

– to making it easier for the programmer. FP 2005 1.14 16 Historical Development of Programming Languages

Emphasis has changed:

± from making life easier for the computer

± to making it easier for the programmer.

Easier for the programmer means: FP 2005 1.15 17 Historical Development of Programming Languages

Emphasis has changed:

± from making life easier for the computer

± to making it easier for the programmer.

Easier for the programmer means:

± Use languages that facilitate writing error-free programs FP 2005 1.16 18 Historical Development of Programming Languages

Emphasis has changed:

± from making life easier for the computer

± to making it easier for the programmer.

Easier for the programmer means:

± Use languages that facilitate writing error-free programs

± Use languages that facilitate writing programs that are easy to maintain FP 2005 1.17 19 Historical Development of Programming Languages

Emphasis has changed:

± from making life easier for the computer

± to making it easier for the programmer.

Easier for the programmer means:

± Use languages that facilitate writing error-free programs

± Use languages that facilitate writing programs that are easy to maintain

Goal of language development: FP 2005 1.18 20 Historical Development of Programming Languages

Emphasis has changed:

– from making life easier for the computer

– to making it easier for the programmer.

Easier for the programmer means:

– Use languages that facilitate writing error-free programs

– Use languages that facilitate writing programs that are easy to maintain

Goal of language development:

– Developers concentrate on design (or even just specification)

– Programming is trivial or handled by computer (executable specification languages, rapid prototyping) FP 2005 1.19 21 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.20 22 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.21 23 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.22 24 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.23 25 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.24 26 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 1.25 27 Important Functional Programming Languages

Functional Programming Languages

pure, statically typed impure

Haskell Clean statically typed dynamically typed

Standard ML LISP, Scheme OCaml APL, J Erlang FP 2005 2.1 29 Haskell FP 2005 2.2 30 Haskell

• functional FP 2005 2.3 31 Haskell

• functional — programs are function definitions FP 2005 2.4 32 Haskell

• functional — programs are function definitions; functions are “first-class citizens” FP 2005 2.5 33 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) FP 2005 2.6 34 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects” FP 2005 2.7 35 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) FP 2005 2.8 36 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed FP 2005 2.9 37 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed FP 2005 2.10 38 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed — all type errors caught at compile-time FP 2005 2.11 39 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed — all type errors caught at compile-time

• type classes — safe overloading FP 2005 2.12 40 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed — all type errors caught at compile-time

• type classes — safe overloading

• Standardised language version: Haskell 98 FP 2005 2.13 41 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed — all type errors caught at compile-time

• type classes — safe overloading

• Standardised language version: Haskell 98

• Several and interpreters available FP 2005 2.14 42 Haskell

• functional — programs are function definitions; functions are “first-class citizens” • pure (referentially transparent) — “no side-effects”

• non-strict (lazy) — arguments are evaluated only when needed

• statically strongly typed — all type errors caught at compile-time

• type classes — safe overloading

• Standardised language version: Haskell 98

• Several compilers and interpreters available

• Comprehensive web site: http://haskell.org/ FP 2005 2.15 43 Important Points FP 2005 2.16 44 Important Points

· Execution of Haskell programs FP 2005 2.17 45 Important Points

· Execution of Haskell programs is expression evaluation FP 2005 2.18 46 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) FP 2005 2.19 47 Important Points

• Execution of Haskell programs is expression evaluation — (for the time being) • Defining functions in Haskell FP 2005 2.20 48 Important Points

• Execution of Haskell programs is expression evaluation — (for the time being) • Defining functions in Haskell is more like defining functions in mathematics FP 2005 2.21 49 Important Points

• Execution of Haskell programs is expression evaluation — (for the time being) • Defining functions in Haskell is more like defining functions in mathematics than like defining procedures in C or classes and methods in Java FP 2005 2.22 50 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) · De®ning functions in Haskell is more like defining functions in mathematics than like de®ning procedures in C or classes and methods in Java · One Haskell function may be de®ned by several ªequationsº FP 2005 2.23 51 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) · De®ning functions in Haskell is more like defining functions in mathematics than like de®ning procedures in C or classes and methods in Java · One Haskell function may be de®ned by several ªequationsº Ð the first that matches is used FP 2005 2.24 52 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) · De®ning functions in Haskell is more like de®ning functions in mathematics than like de®ning procedures in C or classes and methods in Java · One Haskell function may be de®ned by several ªequationsº Ð the ®rst that matches is used · Lists are an easy-to-use datastructure with lots of language and library support FP 2005 2.25 53 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) · De®ning functions in Haskell is more like de®ning functions in mathematics than like de®ning procedures in C or classes and methods in Java · One Haskell function may be de®ned by several ªequationsº Ð the ®rst that matches is used · Lists are an easy-to-use datastructure with lots of language and library support Ð therefore, lists are heavily used in beginners' material. FP 2005 2.26 54 Important Points

· Execution of Haskell programs is expression evaluation Ð (for the time being) · De®ning functions in Haskell is more like de®ning functions in mathematics than like de®ning procedures in C or classes and methods in Java · One Haskell function may be de®ned by several ªequationsº Ð the ®rst that matches is used · Lists are an easy-to-use datastructure with lots of language and library support Ð therefore, lists are heavily used in beginners' material. In many cases, advanced Haskell programmers will use other datastructures, for example Sets, or FiniteMaps instead of association lists. FP 2005 2.27 55 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 = (addition) 4*11-2 (multiplication) FP 2005 2.28 56 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 [subtraction & mult. impossible] = (addition) 4*11-2 (multiplication) FP 2005 2.29 57 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 [subtraction & mult. impossible] = (addition) 4*11-2 (multiplication) FP 2005 2.30 58 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 [subtraction & mult. impossible] = (addition) 4*11-2 [subtraction impossible] (multiplication) FP 2005 2.31 59 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 [subtraction & mult. impossible] = (addition) 4*11-2 [subtraction impossible] = (multiplication) 44-2 FP 2005 2.32 60 Simple Expression Evaluation

The Haskell interpreters hugs, ghci, and hi accept any expression at their prompt and print (after the ®rst ENTER) the value resulting from evaluation of that expression.

Prelude> 4*(5+6)-2 42

Expression evaluation proceeds by applying rules to subexpressions:

4*(5+6)-2 [subtraction & mult. impossible] = (addition) 4*11-2 [subtraction impossible] = (multiplication) 44-2 = (subtraction) 42 FP 2005 2.33 61 Simple Expression Evaluation — Explanation FP 2005 2.34 62 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. FP 2005 2.35 63 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, FP 2005 2.36 64 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed FP 2005 2.37 65 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument FP 2005 2.38 66 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument FP 2005 2.39 67 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . FP 2005 2.40 68 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f undefined = undefined. FP 2005 2.41 69 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned. ± Constant functions are non-strict: FP 2005 2.42 70 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 FP 2005 2.43 71 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: FP 2005 2.44 72 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: null unde®ned = unde®ned FP 2005 2.45 73 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: null unde®ned = unde®ned ± List construction is non-strict: FP 2005 2.46 74 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: null unde®ned = unde®ned

± List construction is non-strict: null ( unde®ned : unde®ned ) = False FP 2005 2.47 75 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: null unde®ned = unde®ned

± List construction is non-strict: null ( unde®ned : unde®ned ) = False ± Standard arithmetic operators are strict in both arguments: FP 2005 2.48 76 Simple Expression Evaluation — Explanation

· Arguments to a fuction or operation are evaluated only when needed. · If for obtaining a result from an application of a function f to a number of arguments, the value of the argument at position i is always needed. then f is called strict in its i-th argument · Therefore: If f is strict in its i-th argument, then the i-th argument has to be evaluated whenever a result is needed from f . · Simpler: A one-argument function f is strict iff f unde®ned = unde®ned.

± Constant functions are non-strict: ( const 5) unde®ned = 5 ± Checking a list for emptyness is strict: null unde®ned = unde®ned

± List construction is non-strict: null ( unde®ned : unde®ned ) = False ± Standard arithmetic operators are strict in both arguments: 0 ∗ unde®ned = unde®ned FP 2005 2.49 77 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111 FP 2005 2.50 78 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) FP 2005 2.51 79 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) FP 2005 2.52 80 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) = 41 * (magic * 42 - 23) (subtraction) FP 2005 2.53 81 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) = 41 * (magic * 42 - 23) (subtraction) = 41 * (7 * 42 - 23) (magic) FP 2005 2.54 82 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) = 41 * (magic * 42 - 23) (subtraction) = 41 * (7 * 42 - 23) (magic) = 41 * (294 - 23) (multiplication) FP 2005 2.55 83 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) = 41 * (magic * 42 - 23) (subtraction) = 41 * (7 * 42 - 23) (magic) = 41 * (294 - 23) (multiplication) = 41 * 271 (subtraction) FP 2005 2.56 84 Unfolding De®nitions

Assume the following de®nitions to be in scope: answer = 42 magic = 7

Expression evaluation will unfold (or expand) de®nitions:

Prelude> (answer - 1) * (magic * answer - 23) 11111

(answer - 1) * (magic * answer - 23) = (42 - 1) * (magic * 42 - 23) (answer) = 41 * (magic * 42 - 23) (subtraction) = 41 * (7 * 42 - 23) (magic) = 41 * (294 - 23) (multiplication) = 41 * 271 (subtraction) = 11111 (multiplication) FP 2005 2.57 85 How did I ®nd those numbers?

Easy!

Prelude> [ n | n <- [1 .. 400] , 11111 `mod` n == 0 ] [1,41,271]

This is a :

· return all n · where n is taken from then list [1 .. 400]

· and a result is returned only if n divides 11111. FP 2005 2.58 86 Conditional Expressions

Prelude> if 11111 `mod` 41 == 0 then 11111 `div` 41 else 5 271 The pattern is:

if condition then expression1 else expression2

± If the condition evaluates to True, the conditional expression evaluates to the value of expression1.

± If the condition evaluates to False, the conditional expression evaluates to the value of expression2. FP 2005 2.59 87 Conditional Expressions

Prelude> if 11111 `mod` 41 == 0 then 11111 `div` 41 else 5 271 The pattern is:

if condition then expression1 else expression2

± If the condition evaluates to True, the conditional expression evaluates to the value of expression1.

± If the condition evaluates to False, the conditional expression evaluates to the value of expression2.

Therefore: ªif _ then _ elseº is strict in the condition. FP 2005 2.60 88 Conditional Expressions

Prelude> if 11111 `mod` 41 == 0 then 11111 `div` 41 else 5 271 The pattern is:

if condition then expression1 else expression2

± If the condition evaluates to True, the conditional expression evaluates to the value of expression1.

± If the condition evaluates to False, the conditional expression evaluates to the value of expression2.

Therefore: ªif _ then _ elseº is strict in the condition.

In C: ( condition ? expression1 : expression2 ) FP 2005 2.61 89 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1) FP 2005 2.62 90 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 FP 2005 2.63 91 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) FP 2005 2.64 92 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) FP 2005 2.65 93 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) FP 2005 2.66 94 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) FP 2005 2.67 95 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) FP 2005 2.68 96 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) FP 2005 2.69 97 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) FP 2005 2.70 98 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) FP 2005 2.71 99 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) FP 2005 2.72 100 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) FP 2005 2.73 101 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) FP 2005 2.74 102 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) FP 2005 2.75 103 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) FP 2005 2.76 104 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) = 3 * 2 * 1 * if True then 1 else 0 * fact (0-1) FP 2005 2.77 105 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) = 3 * 2 * 1 * if True then 1 else 0 * fact (0-1) = 3 * 2 * 1 * 1 FP 2005 2.78 106 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) = 3 * 2 * 1 * if True then 1 else 0 * fact (0-1) = 3 * 2 * 1 * 1 = 3 * 2 * 1 FP 2005 2.79 107 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) = 3 * 2 * 1 * if True then 1 else 0 * fact (0-1) = 3 * 2 * 1 * 1 = 3 * 2 * 1 = 3 * 2 FP 2005 2.80 108 Expanding Function De®nitions fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1)

fact 3 = if 3 == 0 then 1 else 3 * fact (3-1) = if False then 1 else 3 * fact (3-1) = 3 * fact (3-1) = 3 * if (3-1) == 0 then 1 else (3-1) * fact ((3-1)-1) = 3 * if 2 == 0 then 1 else 2 * fact (2-1) = 3 * if False then 1 else 2 * fact (2-1) = 3 * 2 * fact (2-1) = 3 * 2 * if (2-1) == 0 then 1 else (2-1) * fact ((2-1)-1) = 3 * 2 * if 1 == 0 then 1 else 1 * fact (1-1) = 3 * 2 * if False then 1 else 1 * fact (1-1) = 3 * 2 * 1 * fact (1-1) = 3 * 2 * 1 * if (1-1) == 0 then 1 else (1-1) * fact ((1-1)-1) = 3 * 2 * 1 * if 0 == 0 then 1 else 0 * fact (0-1) = 3 * 2 * 1 * if True then 1 else 0 * fact (0-1) = 3 * 2 * 1 * 1 = 3 * 2 * 1 = 3 * 2 = 6 FP 2005 2.81 109 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1) FP 2005 2.82 110 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * (2 * (1 * fact (1-1))) FP 2005 2.83 111 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * (2 * (1 * fact (1-1))) FP 2005 2.84 112 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) FP 2005 2.85 113 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * (1 * fact (1-1))) FP 2005 2.86 114 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) FP 2005 2.87 115 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) FP 2005 2.88 116 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) = 3 * (2 * (1 * fact 0)) (determining which fact rule matches) FP 2005 2.89 117 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) = 3 * (2 * (1 * fact 0)) (determining which fact rule matches) = 3 * (2 * (1 * 1)) (fact 0) FP 2005 2.90 118 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) = 3 * (2 * (1 * fact 0)) (determining which fact rule matches) = 3 * (2 * (1 * 1)) (fact 0) = 3 * (2 * 1) (multiplication) FP 2005 2.91 119 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) = 3 * (2 * (1 * fact 0)) (determining which fact rule matches) = 3 * (2 * (1 * 1)) (fact 0) = 3 * (2 * 1) (multiplication) = 3 * 2 (multiplication) FP 2005 2.92 120 Matching Function De®nitions fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

fact 3 = 3 * fact (3-1) (fact n) = 3 * fact 2 (determining which fact rule matches) = 3 * (2 * fact (2-1)) (fact n) = 3 * (2 * fact 1) (determining which fact rule matches) = 3 * (2 * (1 * fact (1-1))) (fact n) = 3 * (2 * (1 * fact 0)) (determining which fact rule matches) = 3 * (2 * (1 * 1)) (fact 0) = 3 * (2 * 1) (multiplication) = 3 * 2 (multiplication) = 6 (multiplication) FP 2005 2.93 121 Lists

· List display:between square brackets explicitly listing all elements, separated by commas: [1,4,9,16,25] FP 2005 2.94 122 Lists

· List display:between square brackets explicitly listing all elements, separated by commas: [1,4,9,16,25]

· Enumeration lists: denoted by ellipsis ª..º inside square brackets; de®ned by beginning (and end, if applicable): [1 .. 10] = [1,2,3,4,5,6,7,8,9,10] [1,3 .. 10] = [1,3,5,7,9] [1,3 .. 11] = [1,3,5,7,9,11] [11,9 .. 1] = [11,9,7,5,3,1] [11 .. 1] = [] [1 .. ] = [1,2,3,4,5,6,7,8,9,10, …] -- infinite list [1,3 .. ] = [1,3,5,7,9,11, …] -- infinite list FP 2005 2.95 123 List Construction FP 2005 2.96 124 List Construction

Display and enumeration lists are syntactic sugar FP 2005 2.97 125 List Construction

Display and enumeration lists are syntactic sugar: A list is FP 2005 2.98 126 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty FP 2005 2.99 127 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs FP 2005 2.100 128 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) FP 2005 2.101 129 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. FP 2005 2.102 130 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: FP 2005 2.103 131 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] FP 2005 2.104 132 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] FP 2005 2.105 133 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] FP 2005 2.106 134 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] FP 2005 2.107 135 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] FP 2005 2.108 136 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] FP 2005 2.109 137 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right FP 2005 2.110 138 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right:

x : y : ys = x : ( y : ys ) FP 2005 2.111 139 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right:

x : y : ys = x : ( y : ys )

Example: 1 : 2 : [3,4] FP 2005 2.112 140 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right:

x : y : ys = x : ( y : ys )

Example: 1 : 2 : [3,4] = 1 : (2 : [3, 4]) FP 2005 2.113 141 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right:

x : y : ys = x : ( y : ys )

Example: 1 : 2 : [3,4] = 1 : (2 : [3, 4]) = 1 : [2 , 3, 4] FP 2005 2.114 142 List Construction

Display and enumeration lists are syntactic sugar: A list is ± either the empty list: [],

± or non-empty, and constructed from a head x and a tail xs (read: ªxesº) x : xs Ð read: ªx cons xesº. ª:º is used as infix list constructor: 3 : [] = [3] 2 : [3] = [2, 3] 1 : [2, 3] = [1, 2, 3] As an in®x operator, ª:º associates to the right:

x : y : ys = x : ( y : ys )

Example: 1 : 2 : [3,4] = 1 : (2 : [3, 4]) = 1 : [2 , 3, 4] = [1, 2, 3, 4] FP 2005 2.115 143 Cons is Not Associative FP 2005 2.116 144 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. FP 2005 2.117 145 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative: FP 2005 2.118 146 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) FP 2005 2.119 147 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] FP 2005 2.120 148 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4] FP 2005 2.121 149 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] FP 2005 2.122 150 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense FP 2005 2.123 151 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list! FP 2005 2.124 152 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] FP 2005 2.125 153 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]] FP 2005 2.126 154 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]]

· Another list of lists of integers: (1 : [2]) : [[3,4,5], [6,7]] FP 2005 2.127 155 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]]

· Another list of lists of integers: (1 : [2]) : [[3,4,5], [6,7]] = [[1,2],[3,4,5],[6,7]] FP 2005 2.128 156 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]]

· Another list of lists of integers: (1 : [2]) : [[3,4,5], [6,7]] = [[1,2],[3,4,5],[6,7]]

· 1 : ([2] : [[3,4,5], [6,7]]) FP 2005 2.129 157 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]]

· Another list of lists of integers: (1 : [2]) : [[3,4,5], [6,7]] = [[1,2],[3,4,5],[6,7]]

· 1 : ([2] : [[3,4,5], [6,7]]) is nonsense again! FP 2005 2.130 158 Cons is Not Associative

The convention that ª:º associates to the right allows to save parentheses in certain cirtcumstances. However, ª:º is not associative:

· A list of integers: 1 : (2 : [3,4]) = 1 : 2 : [3,4] = [1, 2, 3, 4]

· (1 : 2) : [3,4] is nonsense, since 2 is not a list!

· A list of lists of integers: [2] : [[3,4,5], [6,7]] = [[2],[3,4,5],[6,7]]

· Another list of lists of integers: (1 : [2]) : [[3,4,5], [6,7]] = [[1,2],[3,4,5],[6,7]]

· 1 : ([2] : [[3,4,5], [6,7]]) is nonsense again! Reason: 1 and [2] cannot be members of the same list (type error). FP 2005 2.131 159 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ] FP 2005 2.132 160 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] FP 2005 2.133 161 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] FP 2005 2.134 162 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] FP 2005 2.135 163 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] = [4,16,36,64,100] FP 2005 2.136 164 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] = [4,16,36,64,100] [ m ∗ n | m ← [1,3,5] , n ← [2,4,6] ] FP 2005 2.137 165 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] = [4,16,36,64,100] [ m ∗ n | m ← [1,3,5] , n ← [2,4,6] ] = [2,4,6,6,12,18,10,20,30] FP 2005 2.138 166 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] = [4,16,36,64,100] [ m ∗ n | m ← [1,3,5] , n ← [2,4,6] ] = [2,4,6,6,12,18,10,20,30]

Note: ± The left generator ªgenerates slowerº. FP 2005 2.139 167 List Comprehensions

General shape:

[ term | generator {, generator_or_constraint } ]

Examples: [ n ∗ n | n ← [1 .. 5] ] = [1,4,9,16,25] [ n ∗ n | n ← [1 .. 10] , even n ] = [4,16,36,64,100] [ m ∗ n | m ← [1,3,5] , n ← [2,4,6] ] = [2,4,6,6,12,18,10,20,30]

Note: ± The left generator ªgenerates slowerº.

± Haskell code fragments will frequently be presented like above in a form that is more readable than plain typewriter text Ð in that case, the ªcomes fromº arrow ª<-º in generators turns into ª←º FP 2005 3.2 170 The Type Language

Haskell has a full-fledged type language, with

• Simple predefined datatypes: Bool, Char, Integer, …

• Predefined type constructors: lists, tuples, functions, …

• Type synonyms

• User-defined datatypes and type constructors

• Type variables — to express parametric polymorphism • … FP 2005 3.3 171 Simple Prede®ned Datatypes

Bool truth values False, True Char “Unicode” characters (in GHC: ISO-10646)

Integer integers arbitrary precision Int “machine integers” 32 bits Float real floating point single precision Double real floating point double precision Complex Float complex floating point single precision Complex Double complex floating point double precision FP 2005 3.4 172 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. FP 2005 3.5 173 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 FP 2005 3.6 174 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: ??? FP 2005 3.7 175 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] FP 2005 3.8 176 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: ??? FP 2005 3.9 177 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] FP 2005 3.10 178 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: ??? FP 2005 3.11 179 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] FP 2005 3.12 180 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: ??? FP 2005 3.13 181 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] FP 2005 3.14 182 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: ??? FP 2005 3.15 183 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: [Char] FP 2005 3.16 184 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: [Char] · [ "hello", "world" ] :: ??? FP 2005 3.17 185 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: [Char] · [ "hello", "world" ] :: [[Char]] FP 2005 3.18 186 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: [Char] · [ "hello", "world" ] :: [[Char]] · [["first", "line"], ["second", "line"]] :: ??? FP 2005 3.19 187 List Types

If t is a type, then the list type [t] is the type of lists with elements of type t. answer :: Integer answer = 42 limit :: Int limit = 100 Then: · [ 1, 2, 3, answer] :: [Integer] · [ 1 .. limit ] :: [Int] · [ [ 1 .. limit ] , [ 2 .. limit ] ] :: [[Int]] · [ 'h', 'e', 'l', 'l', 'o' ] :: [Char] · "hello" :: [Char] · [ "hello", "world" ] :: [[Char]] · [["first", "line"], ["second", "line"]] :: [[[Char]]] FP 2005 3.20 188 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). FP 2005 3.21 189 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: ??? FP 2005 3.22 190 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int) FP 2005 3.23 191 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: ??? FP 2005 3.24 192 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer) FP 2005 3.25 193 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ??? FP 2005 3.26 194 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer) FP 2005 3.27 195 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ??? FP 2005 3.28 196 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer)) FP 2005 3.29 197 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ??? FP 2005 3.30 198 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ([Char], Char) FP 2005 3.31 199 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ([Char], Char)

· (limit, ("???", 'X')) :: ??? FP 2005 3.32 200 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ([Char], Char)

· (limit, ("???", 'X')) :: (Int, ([Char], Char)) FP 2005 3.33 201 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ([Char], Char)

· (limit, ("???", 'X')) :: (Int, ([Char], Char))

· (True, [("X",limit),("Y",5)]) :: ??? FP 2005 3.34 202 Product Types (Pairs)

If t and u are types, then the product type (t,u) is the type of pairs with ®rst component of type t and second component of type u (mathematically: t u). Examples:

· (answer, limit) :: (Integer, Int)

· (limit, answer) :: (Int, Integer)

· ("???", answer) :: ([Char], Integer)

· ("???", (limit, answer)) :: ([Char], (Int, Integer))

· ("???", 'X') :: ([Char], Char)

· (limit, ("???", 'X')) :: (Int, ([Char], Char))

· (True, [("X",limit),("Y",5)]) :: (Bool, [([Char], Int)]) FP 2005 3.35 203 Tuple Types

If n / 1 is a natural number and t , ¼ , t are types, then the tuple type 1 n ( , … , ) t1 tn is the type of n-tuples with the ith component of type ti.

Examples:

· (answer, 'c', limit) :: (Integer,Char, Int)

· (answer, 'c', limit, "all") :: (Integer,Char, Int, [Char])

· () :: () Ð there is exactly one zero-tuple. The type () of zero-tuples is also called the unit type. FP 2005 3.36 204 Simple Type Synonyms

If t is a type not containing any type variables, and Name is an identi®er with a capital ®rst letter, then type Name = t de®nes Name as a type synonym for t, i.e., Name can now be used interchangeably with t.

Examples: type String = [Char] − − predefined type Point = (Double, Double) − − (1.5, 2.7) type Triangle = (Point, Point, Point) type CharEntity = (Char, String) − − (’ü’, "ü") type Dictionary = [(String,String)] − − [("day","jour")] FP 2005 3.37 205 Type Variables and Polymorphic Types

· Identi®ers with lower-case ®rst letter can be used as type variables.

· Type variables can be used like other types in the construction of types, e.g.: [(a,b)] (Bool, (a, Int)) [ ( String, [(key, val)] ) ]

· A type containing at least one type variable is called polymorphic

· Polymorphic types can be instantiated by instantiating type variables with types, e.g.:

[(a,b)] [(Char,b)] ⇒ [(a,b)] [(Char,Int)] ⇒ [(a,b)] [(a,[(String,Int)])] ⇒ [(a,b)] [(a,[(String,c)])] ⇒ FP 2005 3.38 206 Typing of List Construction

· The empty list can be used at any list type: [] :: [a]

· If an element x :: a and a list xs :: [a] are given, then (x : xs) :: [a]

Examples: 2 :: Int [] :: [Int] [2] = 2 : [] :: [Int] [[3,4,5], [6,7]] :: [[Int]] [2] : [[3,4,5], [6,7]] :: [[Int]] 1 : ([2] : [[3,4,5], [6,7]]) − − cannot be typed! FP 2005 3.39 207 Function Types and Function Application

If t and u are types, then the function type t->u is the type of all functions accepting arguments of type t and producing results of type u (mathematically: t u). → Then: · If a function f :: a -> b and an argument x :: a are given, then we have (f x) :: b.

· If a function f :: a -> b is given and we know that (f x) :: b, then the argument x is used at type a.

· If an argument x :: a is given and we know that (f x) :: b, then the function f is used at type a -> b. FP 2005 3.40 208 Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) FP 2005 3.41 209 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char FP 2005 3.42 210 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] FP 2005 3.43 211 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ FP 2005 3.44 212 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p FP 2005 3.45 213 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ FP 2005 3.46 214 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ f :: (Int,a) -> Int FP 2005 3.47 215 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ f :: (Int,a) -> Int g h = fst (h "") : [limit] FP 2005 3.48 216 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ f :: (Int,a) -> Int g h = fst (h "") : [limit] h :: String -> (Int,a) ⇒ FP 2005 3.49 217 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit] FP 2005 3.50 218 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 FP 2005 3.51 219 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 = fst (h1 "") : [limit] FP 2005 3.52 220 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 = fst (h1 "") : [limit] = fst (length "", ' ' : "") : [limit] FP 2005 3.53 221 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 = fst (h1 "") : [limit] = fst (length "", ' ' : "") : [limit] = length "" : [limit] FP 2005 3.54 222 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 = fst (h1 "") : [limit] = fst (length "", ' ' : "") : [limit] = length "" : [limit] = 0 : [limit] FP 2005 3.55 223 Let’s Play the Evaluation Game Again — 1 h1 :: String -> (Int, String) h1 str = (length str, ' ' : str) g h = fst (h "") : [limit]

Then: g h1 = fst (h1 "") : [limit] = fst (length "", ' ' : "") : [limit] = length "" : [limit] = 0 : [limit] = [0, 100] FP 2005 3.56 224 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit] FP 2005 3.57 225 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 FP 2005 3.58 226 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] FP 2005 3.59 227 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] = fst (sum (map ord (notOccCaps "")), head "") : [limit] FP 2005 3.60 228 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] = fst (sum (map ord (notOccCaps "")), head "") : [limit] = sum (map ord (notOccCaps "")) : [limit] FP 2005 3.61 229 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] = fst (sum (map ord (notOccCaps "")), head "") : [limit] = sum (map ord (notOccCaps "")) : [limit] = ¼ FP 2005 3.62 230 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] = fst (sum (map ord (notOccCaps "")), head "") : [limit] = sum (map ord (notOccCaps "")) : [limit] = ¼ = 2015 : [limit] FP 2005 3.63 231 Let’s Play the Evaluation Game Again — 2 h2 :: String -> (Int, Char) h2 str = (sum (map ord (notOccCaps str)), head str) notOccCaps :: String -> String notOccCaps str = filter (`notElem` str) ['A' .. 'Z'] g h = fst (h "") : [limit]

Then: g h2 = fst (h2 "") : [limit] = fst (sum (map ord (notOccCaps "")), head "") : [limit] = sum (map ord (notOccCaps "")) : [limit] = ¼ = 2015 : [limit] = [2015, 100] FP 2005 3.64 232 Higher-Order Functions g h = fst (h "") : [limit] FP 2005 3.65 233 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens FP 2005 3.66 234 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens

· Functions can be arguments of other functions: g h2 FP 2005 3.67 235 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens

· Functions can be arguments of other functions: g h2

· Functions can be components of data structures: (7,h1), [h1, h2] FP 2005 3.68 236 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens

· Functions can be arguments of other functions: g h2

· Functions can be components of data structures: (7,h1), [h1, h2]

· Functions can be results of function application: succ . succ FP 2005 3.69 237 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens

· Functions can be arguments of other functions: g h2

· Functions can be components of data structures: (7,h1), [h1, h2]

· Functions can be results of function application: succ . succ

A ®rst-order function accepts only non-functional values as arguments.

A higher-order function expects functions as arguments. FP 2005 3.70 238 Higher-Order Functions g h = fst (h "") : [limit]

Functional Programming: Functions are ®rst-class citizens

· Functions can be arguments of other functions: g h2

· Functions can be components of data structures: (7,h1), [h1, h2]

· Functions can be results of function application: succ . succ

A ®rst-order function accepts only non-functional values as arguments.

A higher-order function expects functions as arguments. g is a second-order function: it expects ®rst-order functions like h1, h2 as arguments. FP 2005 3.71 239 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ f :: (Int,a) -> Int g h = fst (h "") : [limit] h :: String -> (Int,a) ⇒ FP 2005 3.72 240 Type Inference Examples fst :: (a,b) -> a fst (x,y) = x fst ('c', False) :: Char

["hello", fst (x, 17)] x :: String ⇒ f p = limit + fst p p :: (Int,a) ⇒ f :: (Int,a) -> Int g h = fst (h "") : [limit] h :: String -> (Int,a) ⇒ g :: (String -> (Int,a)) -> [Int] FP 2005 3.73 241 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y FP 2005 3.74 242 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol h = (pi :: Double) * r * r * h FP 2005 3.75 243 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol r h = (pi :: Double) * r * r * h Since the right-hand side, r, and h obviously all have type Double, we have; (cylVol r) :: ??? FP 2005 3.76 244 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol r h = (pi :: Double) * r * r * h Since the right-hand side, r, and h obviously all have type Double, we have; (cylVol r) :: Double -> Double FP 2005 3.77 245 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol r h = (pi :: Double) * r * r * h Since the right-hand side, r, and h obviously all have type Double, we have; (cylVol r) :: Double -> Double cylVol :: ??? FP 2005 3.78 246 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol r h = (pi :: Double) * r * r * h Since the right-hand side, r, and h obviously all have type Double, we have; (cylVol r) :: Double -> Double cylVol :: Double -> (Double -> Double) FP 2005 3.79 247 Curried Functions

· Function application associates to the left, i.e., f x y = (f x) y

· Multi-argument functions in Haskell are typically de®ned as curried function, i.e., ªthey accept their arguments one at a timeº: cylVol r h = (pi :: Double) * r * r * h Since the right-hand side, r, and h obviously all have type Double, we have; (cylVol r) :: Double -> Double cylVol :: Double -> (Double -> Double)

· Function type construction associates to the right, i.e., a -> b -> c = a -> (b -> c) FP 2005 3.80 248 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b FP 2005 3.81 249 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ) FP 2005 3.82 250 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ), with · argument type a, · result type b → c. FP 2005 3.83 251 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ), with · argument type a, · result type b → c.

Therefore, we can apply f to x and obtain: FP 2005 3.84 252 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ), with · argument type a, · result type b → c.

Therefore, we can apply f to x and obtain: ( f x ) :: b → c FP 2005 3.85 253 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ), with · argument type a, · result type b → c.

Therefore, we can apply f to x and obtain: ( f x ) :: b → c The application of a ªtwo-argument functionº to a single argument is a ªone-argument functionº FP 2005 3.86 254 ªPartial Applicationº

Let values with the following types be given: f :: a → b → c x :: a y :: b The type of f is the function type a → ( b → c ), with · argument type a, · result type b → c.

Therefore, we can apply f to x and obtain: ( f x ) :: b → c The application of a ªtwo-argument functionº to a single argument is a ªone-argument functionº, which can then be applied to a second argument: ( f x ) y :: c = f x y FP 2005 3.87 255 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ] FP 2005 3.88 256 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) ) FP 2005 3.89 257 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) ) FP 2005 3.90 258 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) FP 2005 3.91 259 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] FP 2005 3.92 260 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate 3 "") ) : [ limit ] FP 2005 3.93 261 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate 3 "") ) : [ limit ] = (3 ∗ ( length "" + 1) ) : [ limit ] FP 2005 3.94 262 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate 3 "") ) : [ limit ] = (3 ∗ ( length "" + 1) ) : [ limit ] = (3 ∗ (0 + 1) ) : [ limit ] FP 2005 3.95 263 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate 3 str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate n "") ) : [ limit ] = (3 ∗ ( length "" + 1) ) : [ limit ] = (3 ∗ (0 + 1) ) : [ limit ] = (3 ∗ 1) : [ limit ] FP 2005 3.96 264 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate 3 "") ) : [ limit ] = (3 ∗ ( length "" + 1) ) : [ limit ] = (3 ∗ (0 + 1) ) : [ limit ] = (3 ∗ 1) : [ limit ] = 3 : [ limit ] FP 2005 3.97 265 Partial Application — Example g :: ( String → ( Int , a ) ) → [ Int ] g h = fst ( h "") : [ limit ]

k :: Int → String → ( Int , String ) k n str = ( n ∗ ( length str + 1) , unwords ( replicate n str ) )

g ( k 3) = fst ( k 3 "") : [ limit ] = fst (3 ∗ ( length "" + 1) , unwords ( replicate 3 "") ) : [ limit ] = (3 ∗ ( length "" + 1) ) : [ limit ] = (3 ∗ (0 + 1) ) : [ limit ] = (3 ∗ 1) : [ limit ] = 3 : [ limit ] = [3, 100] FP 2005 3.98 266 Operations on Functions id :: a -> a − − identity function id x = x

(.) :: (b -> c) -> (a -> b) -> (a -> c) − − function composition (f . g) x = f (g x) flip :: (a -> b -> c) -> (b -> a -> c) − − argument swapping flip f x y = f y x curry :: ((a,b) -> c) -> (a -> b -> c) − − currying curry g x y = g (x,y) uncurry:: (a -> b -> c) -> ((a,b) -> c) uncurryf (x,y) = f x y

Exercise (necessary!): Copy only the de®nitions to a sheet of paper, and then infer the types yourself! FP 2005 3.99 267 Operator Sections

· In®x operators are turned into functions by surrounding them with parentheses: (+) 2 3 = 2 + 3

· This is necessary in type declarations: (+) :: Int -> Int -> Int − − not the ªnaturalº type of (+) (:) :: a -> [a] -> [a] (++) :: [a] -> [a] -> [a]

· It is also possible to supply only one argument (which has to be an atomic expression): (2 +) 3 = 2 + 3 = (+ 3 ) 2 (8,3 /) 2.5 = 8.3 / 2.5 = (/ 2.5) 8.3 (7 :) [] = 7 : [] = (: [] ) 7 ((2^17):) (16:[])= (2^17) : 16 : [] = (: (16:[]))(2^17) FP 2005 3.100 268 Turning Functions into In®x Operators

Surrounding a function name by backquotes turns it into an in®x operator.

Frequently used examples (not the ªnaturalº types throughout): div, mod, max, min :: Int -> Int -> Int elem :: Int -> [Int] -> Bool

12 `div` 7 = 1 12 `mod` 7 = 5 12 `max` 7 = 12 12 `min` 7 = 7 12 `elem` [1 .. 10] = False FP 2005 3.101 269 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool FP 2005 3.102 270 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = FP 2005 3.103 271 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = null ( x : xs ) = FP 2005 3.104 272 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = FP 2005 3.105 273 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False FP 2005 3.106 274 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False

head :: [ a ] → a FP 2005 3.107 275 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False

head :: [ a ] → a head ( x : xs ) = x FP 2005 3.108 276 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False head :: [ a ] → a head ( x : xs ) = x tail :: [ a ] → [ a ] FP 2005 3.109 277 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False head :: [ a ] → a head ( x : xs ) = x tail :: [ a ] → [ a ] tail ( x : xs ) = xs FP 2005 3.110 278 De®ning Functions Over Lists by Pattern Matching

Some functions taking lists as arguments can be de®ned directly via pattern matching: null :: [ a ] → Bool null [ ] = True null ( x : xs ) = False

head :: [ a ] → a head ( x : xs ) = x

tail :: [ a ] → [ a ] tail ( x : xs ) = xs

(head and tail are partial functions Ð both are unde®ned on the empty list.) FP 2005 3.111 279 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ]

product :: [ Integer ] → Integer ( ++ ) :: [ a ] → [ a ] → [ a ]

sum :: [ Integer ] → Integer

( `elem` ) :: Int → [ Int ] → Bool FP 2005 3.112 280 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = concat [ ] = length ( x : xs ) = concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = sum ( x : xs ) = ( x : xs ) ++ ys = product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.113 281 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = length ( x : xs ) = concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = sum ( x : xs ) = ( x : xs ) ++ ys = product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.114 282 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = length ( x : xs ) = 1 + length xs concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = sum ( x : xs ) = ( x : xs ) ++ ys = product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.115 283 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = length ( x : xs ) = 1 + length xs concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = ys sum ( x : xs ) = ( x : xs ) ++ ys = product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.116 284 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = length ( x : xs ) = 1 + length xs concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = ys sum ( x : xs ) = ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.117 285 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) =

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = ys sum ( x : xs ) = ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.118 286 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = [ ] ++ ys = ys sum ( x : xs ) = ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.119 287 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.120 288 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = x + sum xs ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.121 289 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = x + sum xs ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = 0 product ( x : xs ) = x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.122 290 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = x + sum xs ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = 0 product ( x : xs ) = x ∗ product xs x `elem` [ ] = x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.123 291 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = x + sum xs ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = 0 product ( x : xs ) = x ∗ product xs x `elem` [ ] = False x `elem` ( y : ys ) =

(All these functions are in the standard prelude.) FP 2005 3.124 292 De®ning Functions Over Lists by Structural Induction

Many functions taking lists as arguments can be de®ned via structural induction: length :: [ a ] → Int concat :: [ [ a ] ] → [ a ] length [ ] = 0 concat [ ] = [ ] length ( x : xs ) = 1 + length xs concat ( xs : xss ) = xs ++ concat xss

( ++ ) :: [ a ] → [ a ] → [ a ] sum [ ] = 0 [ ] ++ ys = ys sum ( x : xs ) = x + sum xs ( x : xs ) ++ ys = x : ( xs ++ ys ) product [ ] = 0 product ( x : xs ) = x ∗ product xs x `elem` [ ] = False x `elem` ( y : ys ) = x ≡ y || x `elem` ys

(All these functions are in the standard prelude.) FP 2005 3.125 293 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 FP 2005 3.126 294 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!" FP 2005 3.127 295 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] FP 2005 3.128 296 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] FP 2005 3.129 297 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) FP 2005 3.130 298 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : [ ] ) FP 2005 3.131 299 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : [ ] ) FP 2005 3.132 300 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) [ ] FP 2005 3.133 301 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) [ ] = 1 : 2 : 3 : [ ] FP 2005 3.134 302 Guarded De®nitions sign x | x > 0 = 1 | x == 0 = 0 | x < 0 = -1 choose :: Ord a ⇒ ( a , b ) → ( a , b ) → b choose ( x , v ) ( y , w ) | x > y = v | x < y = w | otherwise = error "I cannot decide!"

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3] = take_while ( < 5) (1 : 2 : 3 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) [ ] = 1 : 2 : 3 : [ ] = [1, 2, 3] FP 2005 3.135 303 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] FP 2005 3.136 304 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] FP 2005 3.137 305 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.138 306 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.139 307 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.140 308 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.141 309 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.142 310 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.143 311 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : take_while ( < 5) (3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.144 312 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : take_while ( < 5) (3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : take_while ( < 5) (4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.145 313 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : take_while ( < 5) (3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : take_while ( < 5) (4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : take_while ( < 5) (5 : 4 : 3 : 4 : 5 : 6 : [ ] ) FP 2005 3.146 314 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : take_while ( < 5) (3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : take_while ( < 5) (4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : take_while ( < 5) (5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : [ ] FP 2005 3.147 315 Guarded Definitions — Fall-Through

If no guard succeeds, the next pattern is tried: take_while p ( x : xs ) | p x = x : take_while p xs take_while p xs = [ ] take_while ( < 5) [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 4, 5, 6] = take_while ( < 5) (1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : take_while ( < 5) (2 : 3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : take_while ( < 5) (3 : 2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : take_while ( < 5) (2 : 3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : take_while ( < 5) (3 : 4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : take_while ( < 5) (4 : 3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : take_while ( < 5) (3 : 4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : take_while ( < 5) (4 : 5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : take_while ( < 5) (5 : 4 : 3 : 4 : 5 : 6 : [ ] ) = 1 : 2 : 3 : 2 : 3 : 4 : 3 : 4 : [ ] = [1, 2, 3, 2, 3, 4, 3, 4] FP 2005 3.148 316 case Expressions sign x = case compare x 0 of GT -> 1 EQ -> 0 LT -> -1 FP 2005 3.149 317 case Expressions sign x = case compare x 0 of GT -> 1 EQ -> 0 LT -> -1

The prelude datatype Ordering has three elements and is used mostly as result type of the prelude function compare: data Ordering = LT | EQ | GT FP 2005 3.150 318 case Expressions sign x = case compare x 0 of GT -> 1 EQ -> 0 LT -> -1

The prelude datatype Ordering has three elements and is used mostly as result type of the prelude function compare: data Ordering = LT | EQ | GT

compare :: Ord a ⇒ a → a → Ordering FP 2005 3.151 319 case Expressions sign x = case compare x 0 of GT -> 1 EQ -> 0 LT -> -1

The prelude datatype Ordering has three elements and is used mostly as result type of the prelude function compare: data Ordering = LT | EQ | GT compare :: Ord a ⇒ a → a → Ordering

Another example: choose ( x , v ) ( y , w ) = case compare x y of GT → v LT → w EQ → error "I cannot decide!" FP 2005 3.152 320 if ¼ then ¼ else ¼ and case Expressions

The type Bool can be considered as a two-element enumeration type: data Bool = False | True FP 2005 3.153 321 if ¼ then ¼ else ¼ and case Expressions

The type Bool can be considered as a two-element enumeration type: data Bool = False | True Conditional expressions are ªsyntactic sugarº for case expressions over Bool:

if condition case condition of then expr1 True → expr1 else expr2 False → expr2 FP 2005 3.154 322 if ¼ then ¼ else ¼ and case Expressions

The type Bool can be considered as a two-element enumeration type: data Bool = False | True Conditional expressions are ªsyntactic sugarº for case expressions over Bool:

if condition case condition of then expr1 True → expr1 else expr2 False → expr2

Two ways of de®ning functions:

Pattern Matching case not True = False not b = case b of not False = True True → False False → True FP 2005 3.155 323 case Expressions are ªAnonymousº Pattern Matching commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ case xs of [ ] → [ ] _ → ", " : commaWords xs FP 2005 3.156 324 case Expressions are ªAnonymousº Pattern Matching commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ case xs of [ ] → [ ] _ → ", " : commaWords xs

Every use of a case expression can be transformed into the use of an auxiliary function de®ned by pattern matching FP 2005 3.157 325 case Expressions are ªAnonymousº Pattern Matching commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ case xs of [ ] → [ ] _ → ", " : commaWords xs

Every use of a case expression can be transformed into the use of an auxiliary function de®ned by pattern matching: commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ commaWordsAux xs FP 2005 3.158 326 case Expressions are ªAnonymousº Pattern Matching commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ case xs of [ ] → [ ] _ → ", " : commaWords xs

Every use of a case expression can be transformed into the use of an auxiliary function de®ned by pattern matching: commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ commaWordsAux xs commaWordsAux [ ] = [ ] commaWordsAux xs = ", " : commaWords xs FP 2005 3.159 327 where Clauses FP 2005 3.160 328 where Clauses

If an auxiliary de®nition is used only locally, it should be inside a local de®nition FP 2005 3.161 329 where Clauses

If an auxiliary de®nition is used only locally, it should be inside a local de®nition, e.g.: commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ commaWordsAux xs where commaWordsAux [ ] = [ ] commaWordsAux xs = ", " : commaWords xs FP 2005 3.162 330 where Clauses

If an auxiliary de®nition is used only locally, it should be inside a local de®nition, e.g.: commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ commaWordsAux xs where commaWordsAux [ ] = [ ] commaWordsAux xs = ", " : commaWords xs where clauses are visible only within their enclosing clause, here ªcommaWords ( x : xs ) = …º FP 2005 3.163 331 where Clauses

If an auxiliary de®nition is used only locally, it should be inside a local de®nition, e.g.: commaWords :: [ String ] → String commaWords [ ] = [ ] commaWords ( x : xs ) = x ++ commaWordsAux xs where commaWordsAux [ ] = [ ] commaWordsAux xs = ", " : commaWords xs where clauses are visible only within their enclosing clause, here ªcommaWords ( x : xs ) = …º where clauses are visible within all guards: f x y | y > z = ¼ | y == z = ¼ | y < z = ¼ where z = x * x FP 2005 3.164 332 let Expressions

Local de®nitions can also be part of expressions: f k n = let m = k `mod` n in if m == 0 then n else f n m FP 2005 3.165 333 let Expressions

Local de®nitions can also be part of expressions: f k n = let m = k `mod` n in if m == 0 then n else f n m h x y = let x2 = x * x y2 = y * y in sqrt (x2 + y2) FP 2005 3.166 334 let Expressions

Local de®nitions can also be part of expressions: f k n = let m = k `mod` n in if m == 0 then n else f n m h x y = let x2 = x * x y2 = y * y in sqrt (x2 + y2) De®nitions can use pattern bindings: g k n = let (,m) = divMod k n in if d == 0 then [m] else g d n ++ [m] FP 2005 3.167 335 let Expressions

Local de®nitions can also be part of expressions: f k n = let m = k `mod` n in if m == 0 then n else f n m h x y = let x2 = x * x y2 = y * y in sqrt (x2 + y2) De®nitions can use pattern bindings: g k n = let (d,m) = divMod k n in if d == 0 then [m] else g d n ++ [m] Guards, let and where bindings, and case cases all are layout sensitive! FP 2005 3.168 336 let or where? FP 2005 3.169 337 let or where?

· let bindings in expression is an expression FP 2005 3.170 338 let or where?

· let bindings in expression is an expression

· fname patterns guardedRHSs where bindings is a clause that is part of a de®nition FP 2005 3.171 339 let or where?

· let bindings in expression is an expression

· fname patterns guardedRHSs where bindings is a clause that is part of a de®nition

· (where clauses can also modify case cases) FP 2005 3.172 340 let or where?

· let bindings in expression is an expression

· fname patterns guardedRHSs where bindings is a clause that is part of a de®nition

· (where clauses can also modify case cases)

Frequently, the choice between let and where is a matter of style: · where clauses result in a top-down presentation

· let expressions lend themselves also to bottom-up presentations FP 2005 3.173 341 Some Prelude Functions — Elementary List Access head :: [a] -> a head (x:_) = x last :: [a] -> a last [x] = x last (_:xs) = last xs tail :: [a] -> [a] tail (_:xs) = xs init :: [a] -> [a] init [x] = [] init (x:xs) = x : init xs null :: [a] -> Bool null [] = True null (_:_) = False FP 2005 3.174 342 Some Prelude Functions — List Indexing length :: [a] -> Int length = foldl' (\n _ -> n + 1) 0

(!!) :: [b] -> Int -> b (x:_) !! 0 = x (_:xs) !! n | n>0 = xs !! (n-1) (_:_) !! _ = error "PreludeList.!!:negative index" [] !! _ = error "PreludeList.!!:index too large" FP 2005 3.175 343 Some Prelude Functions — Positional List Splitting take :: Int -> [a] -> [a] take 0 _ = [] take _ [] = [] take n (x:xs) | n>0 = x : take (n-1) xs take _ _ = error "take: negative argument" drop :: Int -> [a] -> [a] drop 0 xs = xs drop _ [] = [] drop n (_:xs) | n>0 = drop (n-1) xs drop _ _ = error "drop: negative argument" splitAt :: Int -> [a] -> ([a], [a]) splitAt 0 xs = ([],xs) splitAt _ [] = ([],[]) splitAt n (x:xs) | n>0 = (x:xs’,xs”) where (xs’,xs”) = splitAt (n-1) xs splitAt _ _ = error "splitAt: negative argument" FP 2005 3.176 344 Some Prelude Functions — Concatenation, Iteration

(++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) concat :: [[a]] -> [a] concat = foldr (++) [] iterate :: (a -> a) -> a -> [a] iterate f x = x : iterate f (f x) repeat :: a -> [a] repeat x = xs where xs = x:xs {− repeat x = x : repeat x −} − − for understanding replicate :: Int -> a -> [a] replicate n x = take n (repeat x) cycle :: [a] -> [a] cycle xs = xs' where xs' = xs ++ xs' FP 2005 3.177 345 Separation of Concerns: Generation and Consumption FP 2005 3.178 346 Separation of Concerns: Generation and Consumption replicate3 '!' FP 2005 3.179 347 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate FP 2005 3.180 348 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat FP 2005 3.181 349 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) FP 2005 3.182 350 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction FP 2005 3.183 351 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat FP 2005 3.184 352 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) FP 2005 3.185 353 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction FP 2005 3.186 354 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction = '!' : '!' : take 1 ('!' : repeat '!') − − repeat FP 2005 3.187 355 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction = '!' : '!' : take 1 ('!' : repeat '!') − − repeat = '!' : '!' : '!' : take (1 - 1) (repeat'!') − − take (iii) FP 2005 3.188 356 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction = '!' : '!' : take 1 ('!' : repeat '!') − − repeat = '!' : '!' : '!' : take (1 - 1) (repeat'!') − − take (iii) = '!' : '!' : '!' : take 0 (repeat'!') − − subtraction FP 2005 3.189 357 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction = '!' : '!' : take 1 ('!' : repeat '!') − − repeat = '!' : '!' : '!' : take (1 - 1) (repeat'!') − − take (iii) = '!' : '!' : '!' : take 0 (repeat'!') − − subtraction = '!' : '!' : '!' : [] − − take (i) FP 2005 3.190 358 Separation of Concerns: Generation and Consumption replicate3 '!' = take 3 (repeat'!') − − replicate = take 3 ('!' : repeat '!') − − repeat = '!' : take (3 - 1) (repeat'!') − − take (iii) = '!' : take 2 (repeat'!') − − subtraction = '!' : take 2 ('!' : repeat '!') − − repeat = '!' : '!' : take (2 - 1) (repeat'!') − − take (iii) = '!' : '!' : take 1 (repeat'!') − − subtraction = '!' : '!' : take 1 ('!' : repeat '!') − − repeat = '!' : '!' : '!' : take (1 - 1) (repeat'!') − − take (iii) = '!' : '!' : '!' : take 0 (repeat'!') − − subtraction = '!' : '!' : '!' : [] − − take (i) = "!!!" FP 2005 3.191 359 What We Have Seen So Far FP 2005 3.192 360 What We Have Seen So Far

· Functional programming: FP 2005 3.193 361 What We Have Seen So Far

· Functional programming: Higher-order functions FP 2005 3.194 362 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results FP 2005 3.195 363 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: FP 2005 3.196 364 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors FP 2005 3.197 365 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism FP 2005 3.198 366 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables) FP 2005 3.199 367 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference FP 2005 3.200 368 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: FP 2005 3.201 369 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator FP 2005 3.202 370 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº FP 2005 3.203 371 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: FP 2005 3.204 372 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: not by value or reference FP 2005 3.205 373 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: not by value or reference, but by name FP 2005 3.206 374 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: not by value or reference, but by name

· Powerful datatypes with simple interface: FP 2005 3.207 375 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: not by value or reference, but by name

· Powerful datatypes with simple interface: Integer, lists, lists of lists of ¼ FP 2005 3.208 376 What We Have Seen So Far

· Functional programming: Higher-order functions, functions as arguments and results · Type systems: type constants and type constructors, parametric polymorphism (type variables), type inference

· Operator precedence rules: juxtaposition as operator, ªassociate to the left/rightº

· Argument passing: not by value or reference, but by name

· Powerful datatypes with simple interface: Integer, lists, lists of lists of ¼

· Non-local control (evaluation on demand): modularity (e.g., generate / prune) FP 2005 3.209 377 Some Prelude Functions — List Splitting with Predicates takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs span, break :: (a -> Bool) -> [a] -> ([a],[a]) span p [] = ([],[]) span p xs@(x:xs') | p x = let (ys,zs) = span p xs' in (x:ys,zs) | otherwise = ([],xs) break p = span (not . p) FP 2005 3.210 378 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs FP 2005 3.211 379 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: FP 2005 3.212 380 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p =

· xs = · x =

· xs' = FP 2005 3.213 381 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = · x =

· xs' = FP 2005 3.214 382 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x =

· xs' = FP 2005 3.215 383 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x = 1

· xs' = FP 2005 3.216 384 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x = 1

· xs' = [2,3] FP 2005 3.217 385 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x = 1

· xs' = [2,3]

· p x = ( < 5) 1 = 1 < 5 = True FP 2005 3.218 386 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x = 1

· xs' = [2,3]

· p x = ( < 5) 1 = 1 < 5 = True

Therefore: dropWhile ( < 5) [1,2,3] = FP 2005 3.219 387 as-Patterns dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [1,2,3]: · p = ( < 5)

· xs = [1,2,3]

· x = 1

· xs' = [2,3]

· p x = ( < 5) 1 = 1 < 5 = True

Therefore: dropWhile ( < 5) [1,2,3] = dropWhile ( < 5) [2,3] FP 2005 3.220 388 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: FP 2005 3.221 389 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p =

· xs = · x =

· xs' = FP 2005 3.222 390 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = · x =

· xs' = FP 2005 3.223 391 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x =

· xs' = FP 2005 3.224 392 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x = 5

· xs' = FP 2005 3.225 393 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x = 5

· xs' = [4,3] FP 2005 3.226 394 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x = 5

· xs' = [4,3]

· p x = ( < 5) 5 = 5 < 5 = False FP 2005 3.227 395 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x = 5

· xs' = [4,3]

· p x = ( < 5) 5 = 5 < 5 = False

Therefore: dropWhile ( < 5) [5,4,3] = FP 2005 3.228 396 as-Patterns — 2 dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs Consider matching of the third clause against dropWhile ( < 5) [5,4,3]: · p = ( < 5)

· xs = [5,4,3]

· x = 5

· xs' = [4,3]

· p x = ( < 5) 5 = 5 < 5 = False

Therefore: dropWhile ( < 5) [5,4,3] = [5,4,3] FP 2005 3.229 397 Some Prelude Functions — List Splitting with Predicates takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile p [] = [] dropWhile p xs@(x:xs') | p x = dropWhile p xs' | otherwise = xs span, break :: (a -> Bool) -> [a] -> ([a],[a]) span p [] = ([],[]) span p xs@(x:xs') | p x = let (ys,zs) = span p xs' in (x:ys,zs) | otherwise = ([],xs) break p = span (not . p) FP 2005 3.230 398 Some Prelude Functions — Text Processing lines :: String -> [String] lines "" = [] lines s = let (l,s') = break ('\n'==) s in l : case s' of [] -> [] (_:sº) -> lines sº words :: String -> [String] words s = case dropWhile isSpace s of "" -> [] s' -> w : words sº where (w,sº) = break isSpace s' unlines :: [String] -> String unlines [] = [] unlines (l:ls) = l ++ '\n' : unlines ls unwords :: [String] -> String unwords [] = "" unwords [w] = w unwords (w:ws) = w ++ ' ' : unwords ws FP 2005 3.231 399 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs FP 2005 3.232 400 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> ([a] -> [a]) filter p [] = [] filter p (x : xs) = if p x then x : rest else rest where rest = filter p xs FP 2005 3.233 401 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> ([a] -> [a]) filter p [] = [] filter p (x : xs) = if p x then x : rest else rest where rest = filter p xs

These functions could also be de®ned via list comprehension: map f xs = [ f x | x <- xs ] FP 2005 3.234 402 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> ([a] -> [a]) filter p [] = [] filter p (x : xs) = if p x then x : rest else rest where rest = filter p xs

These functions could also be de®ned via list comprehension: map f xs = [ f x | x <- xs ] filter p xs = [ x | x <- xs, p x ] FP 2005 3.235 403 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> ([a] -> [a]) filter p [] = [] filter p (x : xs) = if p x then x : rest else rest where rest = filter p xs

These functions could also be de®ned via list comprehension: map f xs = [ f x | x <- xs ] filter p xs = [ x | x <- xs, p x ]

Examples: map (7 *) [1 .. 6] = [7, 14, 21, 28, 35, 42] FP 2005 3.236 404 map and filter map :: (a -> b) -> ([a] -> [b]) map f [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> ([a] -> [a]) filter p [] = [] filter p (x : xs) = if p x then x : rest else rest where rest = filter p xs

These functions could also be de®ned via list comprehension: map f xs = [ f x | x <- xs ] filter p xs = [ x | x <- xs, p x ]

Examples: map (7 *) [1 .. 6] = [7, 14, 21, 28, 35, 42] filter even [1 .. 6] = [2, 4, 6] FP 2005 3.237 405 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs) FP 2005 3.238 406 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 FP 2005 3.239 407 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 = x (foldr1 ( ) [x , x , x , x ]) 1 2 3 4 5 FP 2005 3.240 408 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 = x (foldr1 ( ) [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr1 ( ) [x , x , x ])) 1 2 3 4 5 FP 2005 3.241 409 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 = x (foldr1 ( ) [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr1 ( ) [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr1 ( ) [x , x ]))) 1 2 3 4 5 FP 2005 3.242 410 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 = x (foldr1 ( ) [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr1 ( ) [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr1 ( ) [x , x ]))) 1 2 3 4 5 = x (x (x (x (foldr1 ( ) [x ])))) 1 2 3 4 5 FP 2005 3.243 411 foldr1 foldr1 :: (a -> a -> a) -> [a] -> a foldr1 ( ) [x] = x foldr1 ( ) (x:xs) = x (foldr1 ( ) xs)

foldr1 ( ) [x , x , x , x , x ] 1 2 3 4 5 = x (foldr1 ( ) [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr1 ( ) [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr1 ( ) [x , x ]))) 1 2 3 4 5 = x (x (x (x (foldr1 ( ) [x ])))) 1 2 3 4 5 = x (x (x (x x ))) 1 2 3 4 5 FP 2005 3.244 412 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs) FP 2005 3.245 413 foldrX foldrX :: ( a → b → b ) → b → [ a ] → b foldrX ( ∗∗∗ ) z [ ] = z foldrX ( ∗∗∗ ) z ( x : xs ) = x ∗∗∗ ( foldrX ( ∗∗∗ ) z xs ) FP 2005 3.246 414 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 FP 2005 3.247 415 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 FP 2005 3.248 416 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr ( ) z [x , x , x ])) 1 2 3 4 5 FP 2005 3.249 417 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr ( ) z [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr ( ) z [x , x ]))) 1 2 3 4 5 FP 2005 3.250 418 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr ( ) z [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr ( ) z [x , x ]))) 1 2 3 4 5 = x (x (x (x (foldr ( ) z [x ])))) 1 2 3 4 5 FP 2005 3.251 419 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr ( ) z [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr ( ) z [x , x ]))) 1 2 3 4 5 = x (x (x (x (foldr ( ) z [x ])))) 1 2 3 4 5 = x (x (x (x (x (foldr ( ) z []))))) 1 2 3 4 5 FP 2005 3.252 420 foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr ( ) z [] = z foldr ( ) z (x:xs) = x (foldr ( ) z xs)

foldr ( ) z [x , x , x , x , x ] 1 2 3 4 5 = x (foldr ( ) z [x , x , x , x ]) 1 2 3 4 5 = x (x (foldr ( ) z [x , x , x ])) 1 2 3 4 5 = x (x (x (foldr ( ) z [x , x ]))) 1 2 3 4 5 = x (x (x (x (foldr ( ) z [x ])))) 1 2 3 4 5 = x (x (x (x (x (foldr ( ) z []))))) 1 2 3 4 5 = x (x (x (x (x z)))) 1 2 3 4 5 FP 2005 3.253 421 List Folding foldr :: (a -> b -> b) -> b -> [a] -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) foldr1 :: (a -> a -> a) -> [a] -> a foldr1 f [x] = x foldr1 f (x:xs) = f x (foldr1 f xs) foldl :: (a -> b -> a) -> a -> [b] -> a foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs foldl1 :: (a -> a -> a) -> [a] -> a foldl1 f (x:xs) = foldl f x xs FP 2005 3.254 422 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 FP 2005 3.255 423 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 ∗ ( limit + 1) FP 2005 3.256 424 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 * (limit + 1) = 4 * ((10 ^ 2) + 1) FP 2005 3.257 425 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 * (limit + 1) = 4 * ((10 ^ 2) + 1) = ¼ FP 2005 3.258 426 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 * (limit + 1) = 4 * ((10 ^ 2) + 1) = ¼

Another de®nition: concat = foldr ( ++ ) [ ] FP 2005 3.259 427 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 * (limit + 1) = 4 * ((10 ^ 2) + 1) = ¼

Another de®nition: concat = foldr ( ++ ) [ ] Expanding this de®nition: concat [ [1,2,3] , [4,5] ] FP 2005 3.260 428 Unfolding De®nitions

A simple de®nition: limit = 10 ^ 2 Expanding this de®nition: 4 * (limit + 1) = 4 * ((10 ^ 2) + 1) = ¼

Another de®nition: concat = foldr ( ++ ) [ ] Expanding this de®nition: concat [ [1,2,3] , [4,5] ] = ( foldr ( ++ ) [ ] ) [ [1,2,3] , [4,5] ] = … FP 2005 3.261 429 Enumeration Type De®nitions data Bool = False | True deriving ( Eq , Ord , Read , Show ) data Ordering = LT | EQ | GT deriving ( Eq , Ord , Read , Show ) data Suit = Diamonds | Hearts | Spades | Clubs deriving ( Eq , Ord ) Pattern matching: not False = True not True = False lexicalCombineOrdering :: Ordering → Ordering → Ordering lexicalCombineOrdering LT _ = LT lexicalCombineOrdering EQ x = x lexicalCombineOrdering GT _ = GT FP 2005 3.262 430 Simple data Type De®nitions data Point = Pt Int Int deriving ( Eq ) −− screen coordinates data Transport = Feet | Bike | Train Int −− price in cent This de®nes at the same time data constructors: Pt :: Int → Int → Point Feet :: Transport Bike :: Transport Train :: Int → Transport Pattern matching: addPt ( Pt x1 y1) ( Pt x2 y2 ) = Pt ( x1 + x2 ) ( y1 + y2 ) cost Feet = 0 cost Bike = 0 cost ( Train Int ) = Int FP 2005 3.263 431 Simple Polymorphic data Type De®nitions

The prelude type constructors Maybe, Either, Complex are de®ned as follows: data Maybe a = Nothing | Just a deriving ( Eq , Ord , Read , Show ) data Either a b = Left a | Right b data Complex r = r :+ r deriving ( Eq , Read , Show ) This de®nes at the same time data constructors: Nothing :: Maybe a Just :: a → Maybe a

Left :: a → Either a b Right :: b → Either a b

( :+ ) :: r → r → Complex r