Tuesday, June 30, 2015

Scala's conform idiom

This is an odd little fellow in akka.testkit.TestFSMRef:

class TestFSMRef[S, D, T <: Actor](
  system: ActorSystem,
  props: Props,
  supervisor: ActorRef,
  name: String)(implicit ev: T <:< FSM[S, D])

What is that <:< symbol? It turns out that it comes from Predef, thus:

  sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
  private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
  implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

The documentation says:

Requiring an implicit argument of the type `A <:< B` encodes the generalized constraint `A <: B`.

So, A is a subclass of B. Got it. But how is that enforced for each and every child/parent relationship?

Well, there is a single, implicit $conforms[A] lingering in the ether that insists that A is a superclass or same as A. That's what A <:< A is saying. This is using a type infix operator for syntactic sugar and is equivalent to <:<[A, A].

"A is a superclass or same as A"? This in itself is not terribly useful. However,  <:<[B, A] also must be possible if and only if B is a superclass of A because  <:< is contravariant in its first type (-From) and covariant it its second (+To). That is, <:<[B, A] is a subtype of <:<[A, A] so everything compiles.

So, going back to our original Akka code, the type T <:< FSM[S, D] is enforcing T being a subclass of FSM[S, D] by virtue of there implicitly existing T <:< T and the only way this is satisfied without compilation errors is T <: FSM[S, D].

Friday, June 5, 2015

Monads are easy too!

A lot of people are frightened of Monads for no reason. Perhaps it's because their origins are based in Category Theory. Or that they are used extensively in Haskell. But neither of these need to be understood for the average Java/Scala programmer.

All that needs to be understood are the Monadic Laws (from Coursera):

Monad Laws


(m flatMap f) flatMap g == m flatMap (x => f(x) flatMap g)

Left unit

unit(x) flatMap f == f(x)

Right unit

m flatMap unit == m

(think of unit as just a factory function).

Note: f(x) will return a monadic structure, that is: f is of type X => M[X]  (if x is of type X and m is of type M in the above laws).

Like monoids, monads obey a few simple rules and that's that. So, what's so good about them?

Well, because monoids obey some laws, you can make assumptions about them (eg, when folding, you don't care if it's a left or right fold if you're using monoids).

With monads, you can make similar assumptions. For instance, given these simple functions:

  def addOne(x: Int)            : Int       = x + 1
  def times10(x: Int)           : Int       = x * 10

and this simple monad:

    val option7 = Some(7)

then these two lines are exactly equivalent:

    val outer = option7.flatMap(x => Some(times10(x))).flatMap(x => Some(addOne(x)))
    val inner = option7.flatMap(x => Some(times10(x)).flatMap(x => Some(addOne(x))))

This is useful when dealing with for-comprehensions (which are just syntactic sugar). 

Monads are also used a lot in Haskell as it's a lazy language and they make it actually do something (note: this is not my area of expertise).

The Monad API

Neither Scala nor Java 8 have a common trait or interface that all their monads implement even though they code. For instance, that's exactly what is done in Scalaz.

But, as mentioned, they're used in for-comprehensions in Scala so you might have been using them without even knowing! The compiler doesn't care that the monads don't have a common interface. It knows for-comprehension syntactic sugar can be converted to their respective map and flatMap methods. Then, using the monadic laws above, refactoring for-comprehensions is safe and easy.


So, what monads are is easy. Why they are useful is more subtle. Here is an interesting video on the subject of monads.