// How dot really works
def dotOperator(method : (M<A> -> M<B>), receiver : M<A>) : M<B> = { ... }
def invoke (method : (M<A> -> M<B>), receiver : M<A>) : M<B> = { ... }
// How dot really works
def dotOperator(method : (M<A> -> M<B>), receiver : M<A>) : M<B> = { ... }
def invoke (method : (M<A> -> M<B>), receiver : M<A>) : M<B> = { ... }
// What if the dot operator knew how to unpack an M<A>?
// (Exercise: Why do we care that the operator knows how to unpack M<A>?)
def monadicDotOperator(method : (A -> M<B>), receiver : M<A>) : M<B> = { ... }
// Now let's add the FP jargon back in ;)
def flatmap (method : (A -> M<B>), receiver : M<A>) : M<B> = { ... }
// or:
def bind (method : (A -> M<B>), receiver : M<A>) : M<B> = { ... }
The Monadic Laws--Expressed informally:
1) If you unbox a value and box it again, you'll get "the same"** monad as the original.
2) If you map/flatmap a function f over a boxed value v, the result is "the same" as if you'd computed f(v) directly.
3) Associativity works. If you chain flatmap operations together, executing "the second two operations first" results in the same thing as executing them in order.
** "The same" in a monadic context means that #equals and #hashCode say that the objects are the same, not necessarily that the values are literally the same reference or that they are internally implemented identically.
Formally:
1) m flatmap unit === m
2) unit(x) flatmap f === f(x) === x.f()
3) m flatmap g flatmap f === m flatmap {x => g(x) flatmap f }
(Remember: Unit is the generic name for a monad's 1-arg constructor)
Thanks to James Iry's blog series for this formulation of the Monad Laws.
Informally:
1) If you unbox a value and box it again, you'll get "the same" monad as the original.
2) If you map/flatmap a function f over a boxed value v, the result is "the same" as if you'd computed f(v) directly.
3) Associativity works. If you chain flatmap operations together, executing the second two operations first results in the same thing as executing them in order.
** "The same" in a monadic context means that #equals and #hashCode say that the objects are the same, not necessarily that the values are literally the same reference or that they are internally implemented identically.
Scala's for comprehensions
Haskell's "do-notation" is a syntax to write monad based program fragments:
do
x <- m1
y <- m2
return (x + y)
In Scala, this would look like this:
for(val x <- m1 m1.flatMap { x => m1.flatMap { x =>
val y <- m2) ==becomes==> m2.map { y => i.e. =!= m1.flatMap { x =>
yield {x + y} x+y }} unit (x+y) }}
(From http://lampwww.epfl.ch/~emir/bqbase/2005/01/20/monad.html)
public interface F<A,B> {
B f(A domain);
}
public class IterableMonad {
public static <A, B> Iterable<B> flatmap(Iterable<A> receiver, F<A, Iterable<B>> f) {
}
}