Note:
This blog is intended to record what I learned in Functional Program Design in Scala, rather than share the course materials. So there are two things that I won’t put up: my solution to assignments and topics which I’ve mastered already.
PLEASE NOTIFY ME if I broke Coursera Honor Code accidentally.

Week 1

Lecture 1.1 - Queries with For

• the for notation is essentially equivalent to the common operations of query languages for databases.

Lecture 1.2 - Translation of For

• the Scala compiler translates for-expressions in terms of map, flatMap and a lazy variant of filter.

• we can use for syntax for our own types as long as we define map, flatMap and withFilter for these types.

Lecture 1.3 - Functional Random Generators

• we can use self => at the begining of class/trait body to declare an alias for this.

• define a trait Generator[T] that generates random values of type T:

• how can we avoid the new Generator boilerplate since it’s not trivial? Use for syntax:

• some helper functions:

• [Exercise] how to implement a generator that creates random Tree objects?

• random test: generate random test inputs.

Lecture 1.4 - Monads

• a monad is a parametric type M[T] with two operations: flatMap (in the literature, flatMap is more commonly called bind) and unit, that have to satisfy some laws:

• List is a monad with unit(x) = List(x); Set is monad with unit(x) = Set(x); Generator is a monad with unit(x) = single(x)

• map can be defined for every monad as a combination of flatMap and unit:

• to qualify as a monad, a type has to satisfy three laws:

• associativity:

• left unit:

• right unit:

• [Note] you might find List doesn’t obey the left unit rule since List(1) flatMap (Set(_)) = List(1) != Set(1), this is because the monad law assumes f: A => M[A] (here f: A => List[A]). Refer to link.

• what is the significance of the laws with respect to for syntax?

• associativity says essentially that one can “inline” nested for expressions:

• right unit says:

• left unit does not have an analogue for for-expressions.

• Try is not a monad since it breaks the left unit rule:
• Try(expr) flatMap f != f(expr): left-hand side will never raise a non-fatal exception whereas the right-hand side will raise any exception thrown by expr or f.
• Try trades one monad law for another law which is more useful in this context:
• an expression composed from Try, map, flatMap will never throw a non-fatal exception.

Week 2

Lecture 2.2 - Streams

• streams is similar to lists, but their tail is evaluated only on demand.

• we use #:: instead of :: for stream prepending.

• how to use stream to improve efficiency?

Lecture 2.3 - Lazy Evaluation

• in a purely functional language an expression produces the same result each time it is evaluated.
• lazy evaluation means evaluting on first demand, storing the result of the first evaluation and re-using the stored result instead of recomputing.
• it’s not by-name evaluation where everything is recomputed.
• it’s not restricted evaluation for normal parameters and val definitions.
• Haskell use lazy evaluation by default, but Scala use stricted evaluation by default since it also supports mutable side effects (which might be inharmonious with lazy evaluation) in functions.

Lecture 2.4 - Computing with Infinite Sequences

• define an infinity stream:

• calculate all prime numbers:

• calculate the square root:

Lecture 2.5 - Case Study: the Water Pouring Problem

• a very decent solution to Water Pouring Problem, which is quite worthy of being reviewed.
• some guiding principles for good design:
• name everything you can.
• put operations into natural scopes.
• keep degrees of freedom for future refinements.

Week 3

Lecture 3.2 - Identity and Change

• the precise meaning of “being the same” is defined by the property of operational equivalence.
• x and y are operationally equivalent if no possible test can distinguish between them.

Lecture 3.3 - Loops

• for-loops is not for-expression (end with yield).
• for-loops translate similarly to for-expression, but using foreach combinator instead of map and flatMap.

Week 4

Lecture 4.1 - Imperative Event Handling: The Observer Pattern

• the Observer Pattern is widely used when views need to react to changes in a model. Variants of it are also called:
• publish/subscribe.
• mode/view/controller (MVC).

Lecture 4.2 - Functional Reactive Programming

• imperative reactive programming is about reacting to sequences of events that happen in time, while in functional view: aggregate an event sequence into a signal.
• generally, an indexted argument like f(E1,...,En) = E is translated to f.update(E1,...,En, E), which also works if n = 0.
• sig.update(5) can be abbreviated to sig() = 5.
• we cannot update signal value by s() = s() + 1, since this statement tries to define a signal to be at all points in time one larger than itself.

Lecture 4.7 - Combinators on Futures 2

• do not block when you have asynchronous computation.

Conclusions

How to Apply Functional Design Elements in Applications

• lazy evaluation and infinite data structures
• distinction between computations and values (e.g. a random value acctually is a computation).
• monads to abstract over properties of computation (randomness, delays, effects).
• running computations at some later time.