Comments on "What's Different In Dotty" by Martin Odersky

Posted on 2017-06-03 by Oleg Grenrus

Today I watched a Scala Days 2017 Keynote: "What's Different In Dotty" by Martin Odersky. Even I write Haskell at work (lucky me! not only on free time), it's still interesting to see how other languages evolve.

I think, all the DOT business is very nice, and the dotty is a very good thing. Having sound foundations for the language is a big deal. Note: Do not mix up Scala's System D<: with Haskell's System DC. Dependent stuff everywhere! :)

Also the fact, that dotc (The dotty compiler) is implementing MS Language Server Protocol is a huge deal. I hope that Alan and others will succeed in their Haskell LSP / haskell-ide-engine endeavor!

All so good, but the talk ends with an anticlimax mutable example (around 59:15):

def table(init: implicit Table => Unit) = {
  implicit val t = new Table

def row(init: implicit Row => Unit)(implicit t: Table) = {
  implicit val r = new Row
  t.add(r) // :(

def cell(str: String)(implicit r: Row) =
  r.add(new Cell(str)) // :(

Why? Scala is Object-Oriented Meets Functional.

That DSL can be rewritten in Haskell, in purely functional way. First an import and simple data definitions:

module DifferentDotty where
import Control.Monad.Writer.CPS

newtype Cell  = Cell String deriving Show
newtype Row   = Row [Cell]  deriving Show
newtype Table = Table [Row] deriving Show

Using which we can write the DSL part: the magical implicit is replaced by a spooky(?) Writer monad.

table :: Writer [Row] () -> Table
table = Table . execWriter

row :: Writer [Cell] () -> Writer [Row] ()
row = tell . singleton . Row . execWriter

cell :: String -> Writer [Cell] ()
cell = tell . singleton . Cell

singleton :: a -> [a]
singleton x = [x]

And the usage looks like:

t = table $ do
  row $ do
    cell "top left"
    cell "top right"
  row $ do
    cell "bottom left"
    cell "bottom right"

Compare that to the Scala variant. The two versions are essentially the same (but no mutation!).

table {
  row {
    cell("top left")
    cell("top right")
  row {
    cell("bottom left")
    cell("bottom right")

An exercise: translate the Haskell example to Scala and compare the three versions.

Note: we use WriterT from writer-cps-mtl package. See Gabriel Gonzalez e-mail from 2013 for details about why. Probably should use DList too.

IMHO, it's sad that Martin doesn't seem to like monads. The example above is a simple use of a simple monad, for greater good: referential transparency. In the presentation, right before the DSL example, he showed that implicits are faster than a Reader monad. But that's not true universally. GHC optimizes Reader to be as fast as the explicit argument passing. It would be great if few Ph.D. dissertations will be written (and implemented) about how to make Reader as fast as implicits on JVM platform. Working with monads can be made syntactically pleasant too, for example see Automatically Escaping Monads by Ben Lippmeier, video. I'm sure that work would benefit all functional-style Scala developers, probably also Kotlin and even Java.

You can run this file with

stack --resolver=nightly-2017-03-01 ghci --ghci-options='-pgmL markdown-unlit'
λ> :l DifferentDotty.lhs

fetch the source from

Site proudly generated by Hakyll