Rec 08
Problems
01. Monad and Functors
Every Monad is a Functor! Since it is generalisable, include the implementation of
map()usingof()andflatMap()into the cheatsheet.
The question a) actually proves that given a Monad, we can use its flatMap() and of() to build a map() that satisfies the functor laws.
For example, this is our setup code
import cs2030s.fp.Transformer;
class Monad<T> {
private T x;
private Monad(T x) {
this.x = x;
}
public static <T> Monad<T> of(T x) {
return new Monad<>(x);
}
public T get() {
return x;
}
public <R> Monad<R> flatMap(Transformer<? super T, ? extends Monad<? extends R>> f) {
return new Monad<>(f.transform(this.x).get());
}
}Our map() can be easily implemented as follows
Proof of Functor Laws — Composition Law
When using whatever monad/functor law, find the part of the expression that you are using that law, and replace it with the output of that law.
To find the ultimate proof, try comparing what you want with what you have now. And then slowly slowly prove it.
Suppose we have an instance of
Monad<T>calledmand two functionsfandg.m.map(x -> f(x)).map(x -> g(x))is equivalent to the following Expression A based on our implementation,Exppression A:
m.flatMap(x -> Monad.of(f(x))).flatMap(x -> Monad.of(g(x)))
Invoking Monad's Associative Law on the whole expression, Expression A is equivalent to Expression B below
Expression B:
m.flatMap(x -> Monad.of(f(x)).flatMap(x -> Monad.of(g(x))))
Invoking Monad's Left Identity Law on
Monad.of(f(x)).flatMap(x -> Monad.of(g(x))), this part is equivalent toMonad.of(g(f(x))). Thus, Expression B is equivalent to Expression C belowExpression C:
m.flatMap(x -> Monad.of(g(f(x))))
In our implementation, Expression C is equivalent to
m.map(x -> g(f(x)))Thus, the composition of functions is preserved in our implementation.
Proof of Functor Laws — Identity Law
Suppose we have an instance of Monad<T> called m. "What we want" is m.map(x -> x) = m. So, we start from m.map(x -> x) and slowly derive that it is ultimately equivalent to m.
Using our implementation,
m.map(x -> x)is equivalent tom.flatMap(x -> Monad.of(x)).By invoking Monad's Right Identity Law on the whole expression, we find that it is equivalent to the expression below
m
This is equivalent to "what we want". Thus, the identity law is preserved!
02. Parallel Stream
Calling a 3-parameter
reduce()on a normal stream (not parallelized), we just do the normal reducing method. If samereduce()is called on a parallelized stream (e.g.,stream().parallel()), we cannot decide the final output.
Tips
Every Monad is a Functor! Since it is generalisable, include the implementation of
map()usingof()andflatMap()into the cheatsheet.When using whatever monad/functor law, find the part of the expression that you are using that law, and replace it with the output of that law.
To find the ultimate proof, try comparing what you want with what you have now. And then slowly slowly prove it.
Last updated