0% found this document useful (0 votes)
68 views

Functional Programming Slides

The document provides an overview of functional programming. It aims to introduce readers to the ideas of functional programming using the Haskell programming language. Functional programming is value-oriented and avoids side effects by not using assignments. This paradigm can improve programming skills even for those who do not use functional languages. The document outlines the contents which will cover programming with expressions and values, types, lists, higher-order functions, laziness, and other functional programming concepts.

Uploaded by

cc z
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
68 views

Functional Programming Slides

The document provides an overview of functional programming. It aims to introduce readers to the ideas of functional programming using the Haskell programming language. Functional programming is value-oriented and avoids side effects by not using assignments. This paradigm can improve programming skills even for those who do not use functional languages. The document outlines the contents which will cover programming with expressions and values, types, lists, higher-order functions, laziness, and other functional programming concepts.

Uploaded by

cc z
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 80

Functional Programming

Functional Programming

Ralf Hinze

Universität Kaiserslautern

April 2019

Universität Kaiserslautern — Ralf Hinze 0.0/1-73


Functional Programming

Part 0

Overview

Universität Kaiserslautern — Ralf Hinze 0.0/2-73


Functional Programming

0.0 Outline

Aims

Motivation

Organization

Contents

What’s it all about?

Literature

Universität Kaiserslautern — Ralf Hinze 0.0/3-73


Functional Programming Aims

0.1 Aims

• functional programming is programming with values:


value-oriented programming
• no ‘actions’, no side-effects — a radical departure from
ordinary (imperative or OO) programming
• surprisingly, it is a powerful (and fun!) paradigm
• ideas are applicable in ordinary programming languages too;
aim to introduce you to the ideas, to improve your
programming skills
• (I don’t expect you all to start using functional languages)
• we use Haskell, the standard lazy functional programming
language, see www.haskell.org

Universität Kaiserslautern — Ralf Hinze 0.1/4-73


Functional Programming Motivation

0.2 Motivation
LISP is worth learning [because of] the profound
enlightenment experience you will have when you finally
get it. That experience will make you a better programmer
for the rest of your days, even if you never actually use
LISP itself a lot.

Eric S. Raymond, American computer programmer (1957–)


How to Become a Hacker
www.catb.org/˜esr/faqs/hacker-howto.html

You can never understand one language until you


understand at least two.

Ronald Searle, British artist (1920–2011)

Universität Kaiserslautern — Ralf Hinze 0.2/5-73


Functional Programming Motivation

0.2 FP and OOP

OOP features originating in FP:


• generics e.g. Tree<Elem>
Haskell: parametric polymorphism Tree elem
• type inference
enjoy the benefits of static typing without the pain
• lambda expressions e.g. p −> p.age() >= 18
the core of Haskell \p → age p á 18
• immutable classes and value classes
purity is at the heart of Haskell
• language integrated query languages
Haskell’s list comprehensions
• garbage collection
you don’t want to do without
See Java, C#, F#, Scala etc

Universität Kaiserslautern — Ralf Hinze 0.2/6-73


Functional Programming Motivation

0.2 FP in industry

Some big players:


• facebook: Haskell for spam filtering
• Intel: FP for chip design
• Jane Street, Credit Suisse, Standard Chartered Bank: FP for
financial contracts etc
Some specialist companies:
• galois: FP for high assurance software
• Well-Typed: Haskell consultants

Universität Kaiserslautern — Ralf Hinze 0.2/7-73


Functional Programming Organization

0.3 Organizational matters

• Website: https://pl.cs.uni-kl.de/fp19
• your goal: obtain a good grade
• (my goal: get you interested in FP)
• how to achieve your goal:
ñ make good use of me i.e. attend lectures
ñ make good use of my teaching assistant: Sebastian Schweizer
ñ obtain at least a sufficient grade for 75% of the exercises
ñ work and submit in groups of 3–4
ñ submission: Tuesday 12:00 noon
ñ exercise session: Thursday, 11:45 - 13:15, Room 48-453
ñ pass the final exam
• a gentle request and a suggestion:
keep the use of electronic devices to a minimum;
make notes using pencil and paper

Universität Kaiserslautern — Ralf Hinze 0.3/8-73


Functional Programming Contents

0.4 Contents: part one

1. Programming with expressions and values


2. Types and polymorphism
3. Lists
4. List comprehensions
5. Algebraic datatypes
6. Purely functional data structures
7. Higher-order functions
8. Case study: parser combinators
9. Type classes
10. Case study: map-reduce
11. Reasoning and calculating
12. Algebra of programming

Universität Kaiserslautern — Ralf Hinze 0.4/9-73


Functional Programming Contents

0.4 Contents: part two

13. Lazy evaluation


14. Infinite data structures
15. Imperative programming
16. Functors and theorems for free
17. Applicative functors
18. Monads
19. Type system extensions
20. Class system extensions
21. Duality: folds and unfolds
22. Case study: a duality of sorts
23. Case study: turtles and tesselations

Universität Kaiserslautern — Ralf Hinze 0.4/10-73


Functional Programming What’s it all about?

0.5 Expressions vs statements

• in ordinary programming languages the world is divided into


a world of statements and a world of expressions
• statements:
ñ x := e, s1 ; s2, while e do s
ñ execution order is important
i := i + 1 ; a := a ∗ i ≠ a := a ∗ i ; i := i + 1
• expressions:
ñ a + b ∗ c, a and not b
ñ evaluation order is unimportant: in
(2 ∗ a ∗ y + b) ∗ (2 ∗ a ∗ y + c)
evaluate either parenthesis first (or both simultaneously!)
ñ (assumes no side-effects: order matters in ++x + x−−)

Universität Kaiserslautern — Ralf Hinze 0.5/11-73


Functional Programming What’s it all about?

0.5 Referential transparency


• useful optimizations:
ñ reordering:

x : = 0 ; y : = e ; if x <> 0 then . . . end


= x : = 0 ; if x <> 0 then . . . end ; y : = e
= x := 0 ; y := e

ñ common sub-expression elimination:

z : = (2 ∗ a ∗ y + b ) ∗ (2 ∗ a ∗ y + c )
= t := 2 ∗ a ∗ y ; z := (t + b) ∗ (t + c)

ñ parallel execution: evaluate sub-expressions concurrently


• most optimizations require referential transparency
ñ all that matters about the expression is its value
ñ follows from ‘no side effects’
ñ . . . which follows from ‘no :=’
ñ with assignments, side-effect-freeness is hard to check
Universität Kaiserslautern — Ralf Hinze 0.5/12-73
Functional Programming What’s it all about?

0.5 Programming with expressions

• expressions are much shorter and simpler than the


corresponding statements
• e.g. compare using expression:

z : = (2 ∗ a ∗ y + b ) ∗ (2 ∗ a ∗ y + c )

with not using expressions:

ac : = 2 ; ac ∗= a ; ac ∗= y ; ac += b ; t : = ac ;
ac : = 2 ; ac ∗= a ; ac ∗= y ; ac += c ; ac ∗= t ;
z : = ac

• but in order to discard statements, the expression language


must be extended
• functional programming is programming with an extended
expression language

Universität Kaiserslautern — Ralf Hinze 0.5/13-73


Functional Programming What’s it all about?

0.5 Comparison with ‘ordinary’ programming

• insertion sort
• quicksort
• binary search trees

Universität Kaiserslautern — Ralf Hinze 0.5/14-73


Functional Programming What’s it all about?

0.5 Insertion sort: Modula-2

PROCEDURE InsertionSort ( VAR a : ArrayT ) ;


VAR i , j : CARDINAL ;
t : ElementT ;
BEGIN
FOR i : = 2 TO Size DO
(* a[1..i-1] already sorted *)
t := a[i ] ;
j := i ;
WHILE ( j > 1) AND ( a [ j−1] > t ) DO
a [ j ] : = a [ j−1]; j : = j−1
END ;
a[j] := t
END
END InsertSort ;

Universität Kaiserslautern — Ralf Hinze 0.5/15-73


Functional Programming What’s it all about?

0.5 Insertion sort: Haskell

insertionSort [ ] = []
insertionSort (x : xs) = insert x (insertionSort xs)
insert a [ ] = [a]
insert a (b : xs)
|aàb = a : b : xs
| otherwise = b : insert a xs

Universität Kaiserslautern — Ralf Hinze 0.5/16-73


Functional Programming What’s it all about?

0.5 Quicksort: C

void quicksort ( int a [ ] , int l , int r )


{
if ( r > l )
{
int i = l ; int j = r ;
int p = a [ ( l + r ) / 2 ] ;
for ( ; ; ) {
while ( a [ i ] < p ) i++;
while ( a [ j ] > p ) j−−;
if ( i > j ) break ;
swap(&a [ i+ + ] , &a [ j− −]);
};
quicksort ( a , l , j ) ;
quicksort ( a , i , r ) ;
}
}

Universität Kaiserslautern — Ralf Hinze 0.5/17-73


Functional Programming What’s it all about?

0.5 Quicksort: Haskell

quickSort [ ] = []
quickSort (x : xs) = quickSort littles ++ [x] ++ quickSort bigs
where littles = [a | a ← xs, a < x]
bigs = [a | a ← xs, x à a]

Universität Kaiserslautern — Ralf Hinze 0.5/18-73


Functional Programming What’s it all about?

0.5 Binary search trees: Java

public class BinarySearchTree<Elem> class Empty<Elem extends Comparable<Elem>>


{ implements Tree<Elem> {
private Tree<Elem> root ; public void inorder ( ) {}
public BinarySearchTree ( ) { public Tree insert ( Elem k ) {
root = new Empty ( ) ; return new Node
} ( new Empty ( ) , k , new Empty ( ) ) ;
public void inorder ( ) { }
root . inorder ( ) ; }
}
public void insert ( Elem e ) { class Node<Elem extends Comparable<Elem>>
root = root . insert ( e ) ; implements Tree<Elem> {
} private Elem a ;
} private Tree l , r ;
public Node ( Tree l , Elem a , Tree r ) {
public interface Tree<Elem> { this . l = l ; this . a = a ; this . r = r ;
void inorder ( ) ; }
Tree insert ( Elem e ) ; public void inorder ( ) {
} l . inorder ( ) ;
System . out . println ( a ) ;
r . inorder ( ) ;
}
public Tree insert ( Elem k ) {
if ( k . compareTo ( a ) <= 0)
l = l . insert ( k ) ;
else
r = r . insert ( k ) ;
return this ;
}
}

Universität Kaiserslautern — Ralf Hinze 0.5/19-73


Functional Programming What’s it all about?

0.5 Binary search trees: Haskell

data Tree elem = Empty | Node (Tree elem) elem (Tree elem)
inorder Empty = []
inorder (Node l a r) = inorder l ++ [a] ++ inorder r
insert k Empty = Node Empty k Empty
insert k (Node l a r)
|kàa = Node (insert k l) a r
| otherwise = Node l a (insert k r)

Universität Kaiserslautern — Ralf Hinze 0.5/20-73


Functional Programming Literature

0.6 Literature

• Miran Lipovaca, Learn You a Haskell for Great Good!: A


Beginner’s Guide, No Starch Press, 2011.
• Richard Bird, Thinking Functionally with Haskell, Cambridge
University Press, 2015.
• Paul Hudak, The Haskell School of Expression: Learning
Functional Programming through Multimedia, Cambridge
University Press, 2000.
• Graham Hutton, Programming in Haskell (2nd Edition),
Cambridge University Press, 2016.
• Bryan O’Sullivan, John Goerzen, Don Stewart, Real World
Haskell, O’Reilly Media, 2008.
• Simon Thompson, Haskell: The Craft of Functional
Programming (3rd Edition), Addison-Wesley Professional,
2011.

Universität Kaiserslautern — Ralf Hinze 0.6/21-73


Functional Programming Literature

Part 1

Programming with expressions and values

Universität Kaiserslautern — Ralf Hinze 1.0/22-73


Functional Programming Literature

1.0 Outline

Scripts and sessions

Evaluation

Functions

Definitions

Summary

Universität Kaiserslautern — Ralf Hinze 1.0/23-73


Functional Programming Scripts and sessions

1.1 Calculators

• functional programming is like using a pocket calculator


• user enters in expression, the system evaluates the
expression, and prints result
• interactive ‘read-eval-print’ loop

iiii product [1 . . 40]


815915283247897734345611269596115894272000000000
iiii sort "hello, world\n"
"\n ,dehllloorw"

• powerful mechanism for defining new functions


• we can calculate not only with numbers, but also with lists,
trees, grammars, pictures, music . . .

Universität Kaiserslautern — Ralf Hinze 1.1/24-73


Functional Programming Scripts and sessions

1.1 Scripts and sessions

• we will use GHCi, an interactive version of the Glasgow


Haskell Compiler, a popular implementation of Haskell
• a program is a collection of modules
• a module is a collection of definitions: a script
• running a program consists of loading script and evaluating
expressions: a session
• a standalone program includes a ‘main’ expression
• scripts may or may not be literate (emphasis on comments)

Universität Kaiserslautern — Ralf Hinze 1.1/25-73


Functional Programming Scripts and sessions

1.1 An illiterate script (.hs suffix)

-- compute the square of an integer


square :: Integer -> Integer
square x = x * x

-- smaller of two arguments


smaller :: (Integer, Integer) -> Integer
smaller (x, y) = if x <= y then x else y

Universität Kaiserslautern — Ralf Hinze 1.1/26-73


Functional Programming Scripts and sessions

1.1 A literate script (.lhs suffix)

The following function squares an integer.

> square :: Integer -> Integer


> square x = x * x

This one takes a pair of integers as an argument,


and returns the smaller of the two as a result.
For example,

smaller (3, 4) = 3

> smaller :: (Integer, Integer) -> Integer


> smaller (x, y) = if x <= y then x else y

Universität Kaiserslautern — Ralf Hinze 1.1/27-73


Functional Programming Scripts and sessions

1.1 Layout
• elegant and unobtrusive syntax
• structure obtained by layout, not punctuation
• all definitions in same scope must start in the same column
• indentation from start of definition implies continuation

smaller :: (Integer, Integer) → Integer


smaller (x, y)
= if
xày
then
x
else
y

• leave blank lines around code in literate script!


• use spaces, not tabs!

Universität Kaiserslautern — Ralf Hinze 1.1/28-73


Functional Programming Scripts and sessions

1.1 A session

iiii 42
42
iiii 6 ∗ 7
42
iiii square 7 − smaller (3, 4) − square (smaller (2, 3))
42
iiii square 1234567890
1524157875019052100

Universität Kaiserslautern — Ralf Hinze 1.1/29-73


Functional Programming Evaluation

1.2 Notation: evaluation of expressions

• we use the following layout for evaluations

expr1
=⇒ { why? }
expr2
=⇒ { why? }
expr3

Universität Kaiserslautern — Ralf Hinze 1.2/30-73


Functional Programming Evaluation

1.2 Evaluation
• interpreter evaluates expression by reducing to simplest
possible form
• reduction is rewriting using meaning-preserving
simplifications: replacing equals by equals

square (3 + 4)
=⇒ { definition of ‘+’ }
square 7
=⇒ { definition of square }
7∗7
=⇒ { definition of ‘∗’ }
49

• expression 49 cannot be reduced any further: normal form


• applicative order evaluation: reduce arguments before
expanding function definition (call by value, eager evaluation)
Universität Kaiserslautern — Ralf Hinze 1.2/31-73
Functional Programming Evaluation

1.2 Alternative evaluation orders


• other evaluation orders are possible:

square (3 + 4)
=⇒ { definition of square }
(3 + 4) ∗ (3 + 4)
=⇒ { definition of ‘+’ }
7 ∗ (3 + 4)
=⇒ { definition of ‘+’ }
7∗7
=⇒ { definition of ‘∗’ }
49

• final result is the same: if two evaluation orders terminate,


both yield the same result (confluence)
• normal order evaluation: expand function definition before
reducing arguments (call by need, lazy evaluation)
Universität Kaiserslautern — Ralf Hinze 1.2/32-73
Functional Programming Evaluation

1.2 Values

• in FP, as in maths, the sole purpose of an expression is to


denote a value
• other characteristics (time to evaluate, number of characters,
etc) are irrelevant
• values may be of various kinds: numbers, truth values,
characters, tuples, lists, functions, etc
• important to distinguish abstract value (the number 42) from
concrete representation (the characters ‘4’ and ‘2’, the string
“XLII”, the bit-sequence 0000000000101010)
• evaluator prints canonical representation of value
• some values have no canonical representation (e.g. functions),
some have only infinite ones (e.g. π)

Universität Kaiserslautern — Ralf Hinze 1.2/33-73


Functional Programming Functions

1.3 Functions

• naturally, FP is a matter of functions


• script defines functions (square, smaller)
• (script actually defines values; indeed, in FP functions are
values)
• function transforms (one or more) arguments into result
• deterministic: same arguments always give same result
• may be partial: result may sometimes be undefined
• e.g. cosine, square root; distance between two cities; compiler;
text formatter; process controller

Universität Kaiserslautern — Ralf Hinze 1.3/34-73


Functional Programming Functions

1.3 Function types

• type declaration in script specifies type of function


• e.g. square :: Integer → Integer
• in general, f :: A → B indicates that function f takes arguments
of type A and returns results of type B
• the interface of a function is manifest
• apply function to argument: f x
• sometimes parentheses are necessary: square (3 + 4)
(function application is an operator, binding more tightly than
the operator +)

Universität Kaiserslautern — Ralf Hinze 1.3/35-73


Functional Programming Functions

1.3 Lambda expressions

• notation for anonymous functions (inventing names is hard)


• e.g. \x → x ∗ x as another way of writing square
• x is the formal parameter; x ∗ x is the body of the function
• ASCII ‘\’ is nearest equivalent to Greek λ
• from Church’s λ-calculus theory of computability (1941)

Universität Kaiserslautern — Ralf Hinze 1.3/36-73


Functional Programming Functions

1.3 Lambda expressions

• notation for anonymous functions (inventing names is hard)


• e.g. \x → x ∗ x as another way of writing square
• x is the formal parameter; x ∗ x is the body of the function
• ASCII ‘\’ is nearest equivalent to Greek λ
• from Church’s λ-calculus theory of computability (1941)
• evaluation rule for λ-expressions (β-rule)

(\x → body) arg =⇒ body {x := arg}

• function applied to argument reduces to function body, where


every occurrence of the formal parameter is replaced by the
actual parameter e.g.

(\x → x + x) 47 =⇒ x + x {x := 47} =⇒ 47 + 47 =⇒ 94

Universität Kaiserslautern — Ralf Hinze 1.3/36-73


Functional Programming Functions

1.3 Operators

• functions with alphabetic names are prefix: f 3 4


• functions with symbolic names are infix: 3 + 4
• make an alphabetic name infix by enclosing in back-quotes:
17 ‘mod‘ 10
• make symbolic operator prefix by enclosing it in parentheses:
(+) 3 4
• extend notion to include one argument too: sectioning
• e.g. (1/) is the reciprocal function, (>0) is the positivity test

Universität Kaiserslautern — Ralf Hinze 1.3/37-73


Functional Programming Functions

1.3 Associativity
• why operators at all? why not prefix notation?
• there is a problem of ambiguity:

x⊗y⊗z

what does this mean: (x ⊗ y) ⊗ z or x ⊗ (y ⊗ z)?


• sometimes it doesn’t matter, e.g. addition

(x + y) + z = x + (y + z)

the operator + is associative


• recommendation: use infix notation only for associative
operators
• the operator + has also a unit element

x+0=x=0+x

• 0 and + form a monoid (more later)


Universität Kaiserslautern — Ralf Hinze 1.3/38-73
Functional Programming Functions

1.3 Association

• some operators are not associative (−, /, ˆ)


• to disambiguate without parentheses, operators may associate
to the left or to the right
• e.g. subtraction associates to the left: 5 − 4 − 2 = −1
• function application associates to the left: f a b means (f a) b
• function type operator associates to the right:
Integer → Integer → Integer means
Integer → (Integer → Integer)
• not to be confused with associativity, when adjacent
occurrences of same operator are unambiguous anyway

Universität Kaiserslautern — Ralf Hinze 1.3/39-73


Functional Programming Functions

1.3 Precedence

• association does not help when operators are mixed

x⊕y⊗z

what does this mean: (x ⊕ y) ⊗ z or x ⊕ (y ⊗ z)?


• to disambiguate without parentheses, there is a notion of
precedence (binding power)
• e.g. ∗ has higher precedence (binds more tightly) than +

infixl 7 ∗
infixl 6 +

• function application can be seen as an operator, and has the


highest precedence, so square 3 + 4 = 13

Universität Kaiserslautern — Ralf Hinze 1.3/40-73


Functional Programming Functions

1.3 Composition

• glue functions together with function composition


• defined as follows:

(g ◦ f) x = g (f x)

• equivalent definitions: g ◦ f = \x → g (f x) and


(◦) g f x = g (f x)
• e.g. function square ◦ double takes 3 to 36
• associative, so parentheses not needed in f ◦ g ◦ h

Universität Kaiserslautern — Ralf Hinze 1.3/41-73


Functional Programming Definitions

1.4 Declaration vs expression style

• Haskell is a committee language


• Haskell supports two different programming styles
• declaration style: using equations, patterns and expressions

quad :: Integer → Integer


quad x = square x ∗ square x

• expression style: emphasizing the use of expressions

quad :: Integer → Integer


quad = \x → square x ∗ square x

• expression style is often more flexible


• experienced programmers use both simultaneously

Universität Kaiserslautern — Ralf Hinze 1.4/42-73


Functional Programming Definitions

1.4 Evaluation of expressions: definition style

• e.g. given (declaration style)

spread f g x = (f x) (g x)
kill a x=a

• we calculate

spread kill kill 4711


=⇒ { definition of spread }
(kill 4711) (kill 4711)
=⇒ { definition of kill }
4711

• definitions are applied from left to right

Universität Kaiserslautern — Ralf Hinze 1.4/43-73


Functional Programming Definitions

1.4 Evaluation of expressions: expression style


• e.g. given (expression style)
spread = \f → \g → \x → (f x) (g x)
kill = \a → \x → a
• we calculate
spread kill kill 4711
=⇒ { definition of spread }
(\f → \g → \x → (f x) (g x)) kill kill 4711
=⇒ { β-rule }
(\g → \x → (kill x) (g x)) kill 4711
=⇒ { β-rule }
(\x → (kill x) (kill x)) 4711
=⇒ { β-rule }
(kill 4711) (kill 4711)
..
.
Universität Kaiserslautern — Ralf Hinze 1.4/44-73
Functional Programming Definitions

1.4 Definitions

• we’ve seen some simple definitions of functions so far


• can also define other kinds of values:

name :: String
name = "Ralf"

• all definitions so far have had an identifier (and perhaps


formal parameters) on the left, and an expression on the right
• other forms possible: conditional, pattern-matching, and local
definitions
• also recursive definitions (later sections)

Universität Kaiserslautern — Ralf Hinze 1.4/45-73


Functional Programming Definitions

1.4 Conditional definitions


• earlier definition of smaller used a conditional expression:

smaller :: (Integer, Integer) → Integer


smaller (x, y) = if x à y then x else y

• could also use guarded equations:

smaller :: (Integer, Integer) → Integer


smaller (x, y)
|xày =x
| otherwise = y

• each clause has a guard and an expression separated by =


• last guard can be otherwise (synonym for True)
• especially convenient with three or more clauses
• declaration style: guard; expression style: if ... then ... else...

Universität Kaiserslautern — Ralf Hinze 1.4/46-73


Functional Programming Definitions

1.4 Pattern matching

• define function by several equations


• arguments on lhs not just variables, but patterns
• patterns may be variables or constants (or constructors, later)
• e.g.

day :: Integer → String


day 1 = "Saturday"
day 2 = "Sunday"
day = "Weekday"

• also wild-card pattern


• evaluate by reducing argument to normal form, then applying
first matching equation
• result is undefined if argument has no normal form, or no
equation matches

Universität Kaiserslautern — Ralf Hinze 1.4/47-73


Functional Programming Definitions

1.4 Local definitions


• repeated sub-expression can be captured in a local definition

sqroots :: (Float, Float, Float) → (Float, Float)


sqroots (a, b, c) = ((−b − sd) / (2 ∗ a), (−b + sd) / (2 ∗ a))
where sd = sqrt (b ∗ b − 4 ∗ a ∗ c)

• scope of where clause extends over whole right-hand side


• multiple local definitions can be made:

demo :: Integer → Integer → Integer


demo x y = (a + 1) ∗ (b + 2)
where a = x − y
b =x+y

(nested scope, so layout rule applies here too: all definitions


must start in same column)
• in conjunction with guarded equations, the scope of a where
clause covers all guard clauses
Universität Kaiserslautern — Ralf Hinze 1.4/48-73
Functional Programming Definitions

1.4 let-expressions

• a where clause is syntactically attached to an equation


• also: definitions local to an expression

demo :: Integer → Integer → Integer


demo x y = let a = x − y
b =x+y
in (a + 1) ∗ (b + 2)

• declaration style: where; expression style: let ... in...


• let-expressions are more flexible than where clauses

Universität Kaiserslautern — Ralf Hinze 1.4/49-73


Functional Programming Summary

1.5 The art of functional programming

program
model
problem expression

solve evaluate

solution value
interpret

Universität Kaiserslautern — Ralf Hinze 1.5/50-73


Functional Programming Summary

1.5 The art of functional programming

• a problem is given by an expression


• a solution is a value
• a solution is obtained by evaluating an expression to a value
• a program introduces vocabulary to express problems and
specifies rules for evaluating expressions
• the art of functional programming: finding rules
• Haskell has a very simple computational model
• . . . as in primary school: replacing equals by equals
• we can calculate not only with numbers, but also with lists,
trees, grammars, pictures, music . . .

Universität Kaiserslautern — Ralf Hinze 1.5/51-73


Functional Programming Summary

Part 2

Types and polymorphism

Universität Kaiserslautern — Ralf Hinze 2.0/52-73


Functional Programming Summary

2.0 Outline

Strong typing

Simple types and enumerations

Functions

Tuples

Parametric polymorphism

Type synonyms

Type classes

Summary

Universität Kaiserslautern — Ralf Hinze 2.0/53-73


Functional Programming Strong typing

2.1 Strong typing

• Haskell is strongly typed: every expression has a unique type


• each type supports certain operations, which are meaningless
on other types
• type checking guarantees that type errors cannot occur

Universität Kaiserslautern — Ralf Hinze 2.1/54-73


Functional Programming Strong typing

2.1 Strong typing

• Haskell is strongly typed: every expression has a unique type


• each type supports certain operations, which are meaningless
on other types
• type checking guarantees that type errors cannot occur
• Haskell is statically typed: type checking occurs before
run-time (after syntax checking)
• experience shows well-typed programs are likely to be correct

Universität Kaiserslautern — Ralf Hinze 2.1/54-73


Functional Programming Strong typing

2.1 Strong typing

• Haskell is strongly typed: every expression has a unique type


• each type supports certain operations, which are meaningless
on other types
• type checking guarantees that type errors cannot occur
• Haskell is statically typed: type checking occurs before
run-time (after syntax checking)
• experience shows well-typed programs are likely to be correct
• Haskell can infer types: determine the most general type of
each expression
• wise to specify (some) types anyway, for documentation and
redundancy
• slogan: types don’t just contain data, types explain data

Universität Kaiserslautern — Ralf Hinze 2.1/54-73


Functional Programming Simple types and enumerations

2.2 Simple types

• Booleans
• characters
• strings
• numbers

Universität Kaiserslautern — Ralf Hinze 2.2/55-73


Functional Programming Simple types and enumerations

2.2 Booleans
• type Bool (note: type names capitalized)
• two constants, True and False (note: constructor names
capitalized)
• e.g. definition by pattern-matching

not :: Bool → Bool


not False = True
not True = False

• and &&, or || (both non-strict in second argument, DIY


short-circuit operators: a 6 0 && b / a > 1)

(&&) :: Bool → Bool → Bool


False && = False
True && x = x

• comparisons , 6 , orderings <, à etc

Universität Kaiserslautern — Ralf Hinze 2.2/56-73


Functional Programming Simple types and enumerations

2.2 Boole design pattern

• every type comes with a pattern of definition


• task: define a function f :: Bool → S
• step 1: solve the problem for False

f False = ...

• step 2: solve the problem for True

f False = ...
f True = ...

• (exercise: define your own conditional)

Universität Kaiserslautern — Ralf Hinze 2.2/57-73


Functional Programming Simple types and enumerations

2.2 Characters

• type Char
• constants in single quotes: ’a’, ’?’
• special characters escaped: ’\’’, ’\n’, ’\\’
• ASCII coding: ord :: Char → Int, chr :: Int → Char (defined in
library module Data.Char)
• comparison and ordering, as before

Universität Kaiserslautern — Ralf Hinze 2.2/58-73


Functional Programming Simple types and enumerations

2.2 Strings

• type String
• (actually defined in terms of Char, see later)
• constants in double quotes: "Hello"
• comparison and (lexicographic) ordering
• concatenation +
+
• display function show :: Integer → String (actually more
general than this; see later)

Universität Kaiserslautern — Ralf Hinze 2.2/59-73


Functional Programming Simple types and enumerations

2.2 Numbers

• fixed-precision (32-bit) integers Int


• arbitrary-precision integers Integer
• single- and double-precision floats Float, Double
• others too: rationals, complex numbers, . . .
• comparisons and ordering
• +, −, ∗, ˆ
• abs, negate
• /, div, mod, quot, rem
• etc
• operations are overloaded (more later)

Universität Kaiserslautern — Ralf Hinze 2.2/60-73


Functional Programming Simple types and enumerations

2.2 Enumerations

• mechanism for declaring new types

data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun

• e.g. Bool is not built in (although if ... then ... else syntax is):

data Bool = False | True

• types may even be parameterized and recursive! (more later)

Universität Kaiserslautern — Ralf Hinze 2.2/61-73


Functional Programming Functions

2.3 Functions

• naturally, FP is a matter of functions


• function types: e.g. Char → Int
• X → Y → Z is shorthand for X → (Y → Z)
• values in a similar syntax: \c → ord c − ord ’0’
• i.e. lambda expressions
• recall: c is the formal parameter; ord c − ord ’0’ is the body
of the function
• \x y → z is shorthand for \x → \y → z = \x → (\y → z)
• function application: f x (“space operator”)
• f x y is shorthand for (f x) y

Universität Kaiserslautern — Ralf Hinze 2.3/62-73


Functional Programming Tuples

2.4 Tuples

• pairing types: e.g. (Char, Integer)


• values in the same syntax: (’a’, 440)
• selectors fst, snd
• definition by pattern matching:

fst (x, ) = x

• nested tuples: (Integer, (Char, Bool))


• triples, etc: (Integer, Char, Bool)
• nullary tuple (); the value in the same syntax: ()
• fixed-length sequences of values of (possibly) different types
• comparisons and (lexicographic) ordering

Universität Kaiserslautern — Ralf Hinze 2.4/63-73


Functional Programming Parametric polymorphism

2.5 Parametric polymorphism

• what is the type of fst?


• applicable at different types: fst (1, 2), fst (’a’, True), . . .
• what about strong typing?
• fst is polymorphic — it works for any type of pairs:

fst :: (a, b) → a

• a, b here are type variables (uncapitalized)

Universität Kaiserslautern — Ralf Hinze 2.5/64-73


Functional Programming Parametric polymorphism

2.5 A little game

• here is a little game: I give you a type, you give me a function


of that type
ñ Int → Int
ñ a→a
ñ (Int, Int) → Int
ñ (a, a) → a
ñ (a, b) → a
ñ Int → (Int → Int)
ñ (Int → Int) → Int
ñ a → (a → a)
ñ (a → a) → a
• polymorphic functions: flexible to use, “hard” to define
• polymorphism is a property of an algorithm: same code for
all types

Universität Kaiserslautern — Ralf Hinze 2.5/65-73


Functional Programming Parametric polymorphism

2.5 Type-driven program development

• types are a vital part of any program


• types are not an afterthought
• first specify the type of a function
• its definition is then driven by the type

f :: T → U

• f consumes a T value: suggests


ñ case analysis if T is a datatype (more later)
ñ use of application if T is a function type
• f produces a U value: suggests
ñ use of constructors if U is a datatype (more later)
ñ use of lambda expressions if U is a function type

Universität Kaiserslautern — Ralf Hinze 2.5/66-73


Functional Programming Parametric polymorphism

2.5 Example: code inference


• define a total function of type (((Int → a) → a) → b) → b

Universität Kaiserslautern — Ralf Hinze 2.5/67-73


Functional Programming Parametric polymorphism

2.5 Example: code inference


• define a total function of type (((Int → a) → a) → b) → b
• a function is introduced using a lambda expression
\f → 
• f has type ((Int → a) → a) → b; its body  has type b

Universität Kaiserslautern — Ralf Hinze 2.5/67-73


Functional Programming Parametric polymorphism

2.5 Example: code inference


• define a total function of type (((Int → a) → a) → b) → b
• a function is introduced using a lambda expression
\f → 
• f has type ((Int → a) → a) → b; its body  has type b
• we need to apply the function f
\f → f 
• the argument  of f has type (Int → a) → a

Universität Kaiserslautern — Ralf Hinze 2.5/67-73


Functional Programming Parametric polymorphism

2.5 Example: code inference


• define a total function of type (((Int → a) → a) → b) → b
• a function is introduced using a lambda expression
\f → 
• f has type ((Int → a) → a) → b; its body  has type b
• we need to apply the function f
\f → f 
• the argument  of f has type (Int → a) → a
• a function is introduced using a lambda expression
\f → f (\g →  )
• g has type Int → a; its body  has type a

Universität Kaiserslautern — Ralf Hinze 2.5/67-73


Functional Programming Parametric polymorphism

2.5 Example: code inference


• define a total function of type (((Int → a) → a) → b) → b
• a function is introduced using a lambda expression
\f → 
• f has type ((Int → a) → a) → b; its body  has type b
• we need to apply the function f
\f → f 
• the argument  of f has type (Int → a) → a
• a function is introduced using a lambda expression
\f → f (\g →  )
• g has type Int → a; its body  has type a
• we need to apply the function g
\f → f (\g → g  )
• the argument  of g has type Int
\f → f (\g → g 0)
Universität Kaiserslautern — Ralf Hinze 2.5/67-73
Functional Programming Parametric polymorphism

2.5 Parametric polymorphism

• h is polymorphic — it works for any type a and any type b

h :: (((Int → a) → a) → b) → b
h = \f → f (\g → g 0)

• parametric polymorphism: same code for all types


• values of type a and b are not “inspected” — they are treated
as black boxes
• they are only passed around (or ignored, or duplicated)
• algorithm is insensitive to parts of the data

Universität Kaiserslautern — Ralf Hinze 2.5/68-73


Functional Programming Type synonyms

2.6 Type synonyms

• alternative names for types


• brevity, clarity, documentation
• e.g.

type Card = (Rank, Suit)

• cannot be recursive
• just a ‘macro’: no new type

Universität Kaiserslautern — Ralf Hinze 2.6/69-73


Functional Programming Type classes

2.7 Type classes

• what about numeric operations?


• (+) :: Integer → Integer → Integer
• (+) :: Float → Float → Float
• cannot have (+) :: a → a → a (too general)
• the solution is type classes (sets of types)
• e.g. the type class Num is a set of numeric types; includes
Integer, Float, etc
• now (+) :: (Num a) ⇒ (a → a → a)
• ad-hoc polymorphism (different code for different types), as
opposed to parametric polymorphism (same code for all types)

Universität Kaiserslautern — Ralf Hinze 2.7/70-73


Functional Programming Type classes

2.7 Some standard type classes

• Eq: ,6
• Ord: < etc, min etc
• Enum: succ, . .
• Bounded: minBound, maxBound
• Show: show :: a → String
• Read: read :: String → a
• Num: +, ∗ etc
• Real (ordered numeric types)
• Integral: div etc
• Fractional: / etc
• Floating: exp etc
• more later

Universität Kaiserslautern — Ralf Hinze 2.7/71-73


Functional Programming Type classes

2.7 Derived type classes

• new datatypes are not automatically instances of type classes


• possible to install as instances:

data Gender = Female | Male


instance Eq Gender where
Female Female = True
Female Male = False
Male Female = False
Male Male = True

• (default definition of 6 obtained for free from , more later)


• tedious for simple cases, which can be derived automatically:

data Gender = Female | Male


deriving (Eq, Ord, Enum, Bounded, Show, Read)

Universität Kaiserslautern — Ralf Hinze 2.7/72-73


Functional Programming Summary

2.8 Summary

• type-driven program development


• type safety and flexibility are in tension
• polymorphism partially releases the tension
• ad-hoc polymorphism: different code for different types
• parametric polymorphism: same code for all types

Universität Kaiserslautern — Ralf Hinze 2.8/73-73

You might also like