Lecture 7
Lecture 7
Lecture 7: Foundations of
Functional Programming
3
Properties of Functions
A B
n Injective
q One-to-one or embedding if a function maps distinct
elements of A to distinct elements of B A B
n Surjective
q Onto if the range of a function is the codomain of B
A B
n Bijective = injective + surjective
n Inverse Functions
q If f: A ® B is a bijection, then there is an inverse function
g: B ® A s.t. g(b) = a if f(a) = b
n If there is an injection from A to B, then there is a
surjection from B to A, and conversely
4
Modeling Function to Add Integers
interface AddIntegersFunction {
default Integer add(Integer a, Integer b){
return a+b;
}
}
}
} String String
(a,b)
interface AddDiverseGenericFunction<A,B,C> {
C add(A a, B b);
}
}
}
Integer, Double String
(a,b)
interface AddDiverseGenericEmptyFunction<A,B,C> {
}
interface FileHandler<T>{
T handler(File file);
}
class DecartesCoordinates {
private Integer x = 0;
private Integer y = 0;
class GradePoint {
class DecartesCoordinates {
private Integer grade = 0;
private Integer x = 0;
private Double weight = 0e0;
private Integer y = 0;
public GradePoint(Integer grade, Double weight) {
public DecartesCoordinates(Integer x, Integer y) { this.grade = grade;
this.x = x; this.weight = weight;
this.y = y; }
}
public Double grade() {
public Double distance() { return grade * weight;
return Math.sqrt(x * x + y * y); }
} }
}
public class ComputingGpaAverage {
public class PuttingConsumerInterface2Use { public static void main(String[] args) {
public static void main(String[] args) { List<GradePoint> grades =
List<DecartesCoordinates> coordinates = new ArrayList<GradePoint>();
new ArrayList<DecartesCoordinates>(); grades.add(new GradePoint(5, 1.));
coordinates.add(new DecartesCoordinates(1, 2)); grades.add(new GradePoint(2, 0.2));
coordinates.add(new DecartesCoordinates(2, 10)); Double sum = 0e0;
for (GradePoint g : grades) {
for (DecartesCoordinates c : coordinates) {
sum += g.grade();
System.out.println(c.distance());
}
}
System.out.println(sum/grades.size());
}
}
} }
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
coordinates.forEach(new PuttingConsumerInterface2Use());
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
coordinates.forEach(new PuttingConsumerInterface2Use());
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
coordinates.forEach(elem.mapsTo(elem.distance()));
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
coordinates.forEach(elem.mapsTo(elem.distance()));
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
F: DecartesCoordinates => Double
coordinates.forEach(elem.mapsTo(elem.distance()));
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
F: DecartesCoordinates => Double
coordinates.forEach(elem=>elem.distance());
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
F: DecartesCoordinates => Double
coordinates.forEach(elem->distance());
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
F: DecartesCoordinates => Double
coordinates.forEach(distance);
}
@Override
public void accept(DecartesCoordinates decartesCoordinates) {
System.out.println(decartesCoordinates.distance());
}
}
import java.util.ArrayList;
import java.util.List;
λf λu
λx λf
λx
left-associative
(u f)x
f fx
f
(f: Int->int, x: Int) => f(f(x))
(λf. (λx.(f(f x))) sqrt) 81 => x
(λx.(sqrt(sqrt x))) 81 =>
sqrt (sqrt 81) => 3 u f
n Evaluate f 0
q f is the function λa.x, it returns the value λf λa
of x no matter what the argument is
x
q What is the value of x?
q The closure is f→ (λa.x, [x→1]) λx 2
f 0
Department of Computer Science, the
University of Illinois at Chicago 44
Identity λ functions
49
Partial and Total Functions
50
How to Construct Functions
n Composition
q (f ° g)(x) = f(g(x))
q cos: R+ ® R and log2 : R+ ® R, cos ° log2: R+ ® R
n The Map Function
q map(f, <x1,…xn>) = <f(x1),… f(xn)>
q map(+, <(1,2),(3,4),(5,6)>) = <3, 7, 11>
q map: (A ® B) ´ list(A) ® list(B)
n Importance of function composition concept
51
An Algebra of Functions
n Let S be a set, and let F be the set of all functions of
type S ® S. Let ° denote the operation of
compositions of functions. Then F is the set of an
algebra <F; °, id> where id is the identity function:
id °f = f °id = f for all functions f in F
n Algebras
q Groupoid: ° is a binary operation
q Semigroup: ° is an associative binary operation
q Monoid: ° is an associative binary operation with an identity
q Group: ° is an associative binary operation with an identity
and every element has an inverse
52
Recursion
n A function or procedure (a program that performs one or more
actions) is recursively defined if it is defined in terms of itself
n If A is an inductively defined set, then we can construct a function f
with domain A as follows
q For each basis element a in A, specify a value for f(a)
q Give rules that, for any inductively defined element a in A, will define f(a)
in terms of previously defined values of f
n Fibonacci numbers
q 0,1,1,2,3,5,8,13,21,34,55,…
q Let fib(n) be the nth Fibonacci number
q fib(0) = 0
q fib(1) = 1
q fib(n) = fib(n-1) + fib(n-2) for n >= 2
q fib(n+2) = fib(n+1) + fib(n) for n>0
53
Recursive Definition of Lists
54
Program By Composing Functions