Functional Programming - FP101

- UNIFEI - October - 2018

Hello!

Prof. Edmilson

Hanneli Tavante

<3

Prolog

Prof. Maurilio

<3

Deutschland

Questions

• What is this course?
• A: An attempt to bring interesting subjects to the courses at UNIFEI
• Why are the slides in English?
• I am reusing some material that I prepared before
• What should I expect?
• This is the first time we give this course. We will be looking forward to hearing your feedback

Rules

• Don't skip classes
• The final assignment is optional
• We will have OPTIONAL assignments during the classes
• Feel free to ask questions
• Don't feel discouraged with the mathematics
• Contact us for study group options

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4. Lists (gotta love them)
5. Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Note: this list can change

WAT

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types and classes
4. Lists (gotta love them)
5. Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Note: this list can change

[1, 2, 3, 4, 5]

Is this the only way to solve this?

No.

[1, 2, 3, 4, 5].map { |el| el*2 }
=> [2, 4, 6, 8, 10]

Which language is this??

A: Ruby!

[ el*2 for el in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10]

Which language is this??

A: Python!

[ el*2 | el <- [1..5] ]
[2, 4, 6, 8, 10]

Which language is this??

List(1, 2, 3, 4, 5).map( el => el*2)
res0: List[Int] = List(2, 4, 6, 8, 10)

Which language is this??

A: Scala!

fn main() {
let res = vec![1, 2, 3, 4, 5].iter()
.map(|&el| el*2).collect::<Vec<_>>();
println!("{:?}", res);
}
[2, 4, 6, 8, 10]

Which language is this??

A: Rust!

There are different styles to write code (paradigm)

There is one style of programming in which expressions are more important than statements

Note: examples of statements: for, do/while, {...}, return

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4. Lists (gotta love them)
5. Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Challenge: Create a program to sum the numbers from 0 to 100 (including 100)

//pseudocode

int res = 0;
for (int i=0; i<= 100; i++) {
res = res + i;
}

What are the problems of this code?

Is there anything you can't predict?

There are two things to be aware:

res: 5050

sum[1..100]
5050

sum[1..100]

sum()

1..100

Some historical background

Turing

Alonzo Church

"How can we formalize the concept of effective computability?"

Turing Machines

Lambda Calculus

Like the calculus you see at MAT001, λ-calculus is a formalism

J. McCarthy

Lisp Programming Language - one of the first functional languages

Functional Programming => One way to implement λ-calculus formalisms

Other languages: ML, Haskell

Why is this programming style so important?

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4. Lists (gotta love them)
5. Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Data

Operations

Wait - what is a type?

Type: a name for a collection of related values

{ True, False }: Bool

Wait - what is a type system?

"In programming languages, a type
system is a collection of rules
that assign a property called
type to various constructs a
computer program consists of, such
as variables, expressions, functions
or modules"

Strategies

• Generate a compile error
• Perform a type check before run the code
• Well defined error set
• Unpredictable  runtime errors
• Try implicit conversion
• A compiler tags pieces of code and tries to infer if the behaviour will be valid or not (before the program runs)
• A compiler / interpreter generates code to keep track of the data

Strategies

• Generate a compile error
• Perform a type check before run the code
• Well defined error set
• Unpredictable  runtime errors
• Try implicit conversion
• A compiler tags pieces of code and tries to infer if the behaviour will be valid or not (before the program runs)
• A compiler / interpreter generates code to keep track of the data

"Strong"

"Weak"

"Static"

"Dynamic"

* Definitions are not exact on literature

You don't have to choose only one alternative

Java: static (why?)

Python: dynamic

Can you see the benefits of statically typed languages?

• A compiler tags pieces of code and tries to infer if the behaviour will be valid or not (before the program runs)

"Static"

Benefits of statically typed languages

1. Reduce the number of runtime errors

Benefits of statically typed languages

2. The compiler can calculate the type of an expression

Type inference

Benefits of statically typed languages

3. The type the compiler calculates corresponds to the type you obtain when you execute the expression in runtime

Type Soundness

Basic Types

• Lists

(group of elements, the types can be different)

• Tuples

(Sequence of values where all the elements have the same type)

expr::type

This is the terminology we use to indicate that an expression has a certain type (::)

Prelude> :type 1
1 :: Num t => t

Functions also have types

Can you put 'Function' and 'type' in the same sentence so that you can come up with a definition of function?

"Function is a mapping of values from one type to another type"

An exercise

Let's write a function to sum two integers in Haskell

Attempt #1

addd (x, y) = x+y
7

Attempt #2

addd x y = x+y
7

What is the difference?

What is the difference?

Attempt #1

addd (x, y) = x+y
7

Attempt #2

addd x y = x+y
7
addd :: Num a => (a, a) -> a
addd :: Num a => a -> a -> a

Attempt #2

addd x y = x+y
7
addd :: Num a => a -> a -> a

There is an advantage in writing the function like this:

It is a function (1)

That returns a function (2)

That takes another number (3)

And returns a number (4)

Attempt #2

addd x y = x+y
7
addd :: Num a => a -> a -> a

There is an advantage in writing the function like this:

addd :: Num a => a -> (a -> a)

Is equivalent to:

Remember: Arrows associate to the right (*)

Attempt #2

addd x y = x+y
7
addd :: Num a => a -> (a -> a)

Now it is easier to see:

It is a function (1)

That returns a function (2)

That takes another number (3)

And returns a number (4)

a Curried Function

addd :: Num a => a -> a -> a

Remember: Arrows associate to the right

(*)

addd :: Num a => a -> (a -> a)

Remember: Function applications associates to the left

mult x y z
((mult x) y) z

Question: Does addd work for float numbers?

addd :: Num a => a -> (a -> a)
6.300000000000001

How can we restrict that to Integers only?

addd     :: Int -> (Int -> Int)
addd x y = x+y
addd :: Int -> Int -> Int
error: No instance for
(Fractional Int)
arising from the literal ‘3.1’

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists (gotta love them)
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Lists

[1, 2, 3, 4, 5]

What are lists in terms of expressions?

Whiteboard time! Let's understand the x:xs notation

What are lists in terms of expressions?

1:(2:(3:(4:(5:[ ]))))

How do we manipulate lists?

(ex: transform elements into other elements, get only specific elements, transform lists into tuples)

A: List Comprehensions

List comprehensions

[x^2 | x <- [1..5]]

generator:

defines how to generate the values of x

function to

transform x

Filters

[x | x <- [1..5], even x]

Get the number, no transformation

Get only the even numbers of a list

generator

filter

Challenge: Determine the position(s) of an element in a list

positions 2 [1, 2, 3, 4, 5, 2, 1, 3]

A: 1 and 5

Problem: Lists do not have an index!

Start rom the beginning

positions

function name

x
xs

el

list

=

Strategy: transform each element of the list in a tuple: (el, pos)

The solution

[1, 2, 3, 4, 5, 2, 1, 3]

Our list

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Solution

(1, 0)
,(2, 1)
,(3, 2)
[

...

zip

operation

The code

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Goal

[(1, 0), (2, 1) ...]

zip

operation

positions x xs =
zip xs [1, 2, 3, 4, 5, 2, 1, 3]

The code

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Goal

[(1, 0), (2, 1) ...]

zip operation

positions x xs =
zip xs [1..n]
where n = length xs - 1

The code

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Goal

[(1, 0), (2, 1) ...]

zip operation

positions x xs =
zip xs [1..n]
where n = length xs - 1
<-
(  ,  )

el, pos

get pos

i |

The code

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Goal

[(1, 0), (2, 1) ...]

zip operation

positions x xs =
zip xs [1..n]
where n = length xs - 1
<-
(  , i)

el, pos

list comprehension

i |
[

Now we need to filter the elements that we specified

The code

[0, 1, 2, 3, 4, 5, 6, 7]

Positions

Goal

[(1, 0), (2, 1) ...]

zip operation

positions x xs =
zip xs [1..n]
where n = length xs - 1
<-
(  , i)

el, pos

list comprehension

i |
[
,
x'== x
(x', i)
]

Break

What are functions?

Remember, Haskell has a strong link to mathematics

In λ-calculus, we have λ expressions

\lambda x -> x+x
$\lambda x -> x+x$

expression that denotes functions

λ:

Let's give it a try

Write the addd function as a  λ expression

addd x y = x+y
add = \lambda x \rightarrow ( \lambda y \rightarrow x+y )
$add = \lambda x \rightarrow ( \lambda y \rightarrow x+y )$

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Why is recursion such a nice feature?

One reason is being able to prove properties by mathematical induction :)

The practical reason here is that it helps us to get rid of statements

Challenge - write a length function using recursion

1. Let's define the types

length    ::
[a]
-> Int

Challenge - write a length function using recursion

1. Let's define the types

length    ::
[a]
-> Int

2. Define the base case

The "base case" is the one that will not change the result

length [] = 0

Challenge - write a length function using recursion

1. Let's define the types

length    ::
[a]
-> Int

2. Define the base case

length [] = 0

3. Define the recursive structure

Add one to each element of the list, until you get an empty list

Remember: this is a list

1:(2:(3:(4:(5:[ ]))))

Challenge - write a length function using recursion

1. Let's define the types

length    ::
[a]
-> Int

2. Define the base case

length [] = 0

3. Define the recursive structure

length (  : xs) = 1 + length xs

Anything

(_ : xs)

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Whiteboard time

Use this video for reference (Computerphile)

There is an important question none asked:

How are expressions evaluated?

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Lazy Evaluation

Agenda

1. Foundation concepts; intro to Programming Languages
2. Why Functional Programming (FP)?
3. Types
4.  Lists
5.  Recursion
6. Higher order functions (Hof)
8. Lazy Evaluation
9. A word or two about Lambda Calculus
10. Final considerations

Exercise - Section 5 of this paper +

Church Numerals

References

Functional Programming - FP101

By Hanneli Tavante (hannelita)

• 352