@felixmulder

Programming Multicores in Scala

Past, Present, Future

Felix Mulder

  • felixmulder
  • felixmulder.com

So, why scala?

Types

Types

Types

val x = 1 // x: Int
def foo[A](a: A): a.type = a
trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}
implicit val ListFunctor = new Functor[List] {
  def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}

def compose[F[_]: Functor, A, B, C](fa: F[A])(f: B => C, g: A => B) =
  F.map(fa)(f compose g)

Make illegal state unrepresentable

Finite State Machine

trait State {
  type NewState <: State
  type Transition
}

case class TurnOn()
case class TurnOff()

case object On {
  type Transition = TurnOff
  type NewState = Off
}

case object Off {
  type Transition = TurnOn
  type NewState = On
}

case object Broken {
  type Transition = Nothing
  type NewState = Broken
}



def trans[S <: State](event: S#Transition, target: S#NewState): S#NewState =
  target

def trans[S <: State](implicit ev: S#Transition =:= Nothing, t: ValueOf[S#NewState]): S#NewState =
  t.value

The big picture

  • Correct
  • Scalable
  • Fast
  • Actors
  • Futures and friends
  • Distributed programming models

Actors

class MyActor extends Actor {
  def receive = {
    case "ping" => sender ! "pong"
  }
}

Actors

Pros

  • Cheap
  • Easy to bootstrap
  • Akka

Actors

Cons?

Untyped 😰


case class StartPong(ref: ActorRef)

class Pinger extends Actor {
  def receive = {
    case StartPong(ref) => ref ! "ping"
    case "pong"         => sender ! "ping"
  }
}

class Ponger extends Actor {
  def receive = {
    case "ping" => sender ! Expletive.random
  }
}
[error] scala.MatchError: Expletive(@#!$) (of class Expletive)
  ... 36 elided
😡
def receive: PartialFunction[Any, Unit]

🤦‍♂️

Can we remedy this?


case class StartPong(ref: ActorRef)


class Pinger extends Actor {
  def receive = {
    case StartPong(ref) => ref ! "ping"
    case "pong"         => sender ! "ping"
  }
}
                                                                   
class Ponger extends Actor {
  def receive = {
    case "ping" => sender ! Expletive.random
  }
}

case class Pong(ref: TypedActorRef[Ping])
case class Ping(ref: TypedActorRef[Pong])

class Pinger extends TypedActor[Pong] {
  def receive = {
    case Pong(ref) => sender ! Ping(self)
  }
}

class Ponger extends TypedActor[Ping] {
  def receive = {
    case Ping(ref) => sender ! Expletive.random // still compiles 😰
  }
}

case class Pong(ref: TypedActorRef[Ping])
case class Ping(ref: TypedActorRef[Pong])

class Pinger extends TypedActor[Pong] {
  def receive = {
    case Pong(ref) => ref ! Ping(self)
  }
}

class Ponger extends TypedActor[Ping] {
  def receive = {
    case Ping(ref) => ref ! Expletive.random // doesn't compile! 😬 
  }
}

akka-typed

Future[T]
def map[B](f: A => B)(implicit EC: ExecutionContext): Future[B]

def flatMap[B](f: A => Future[B])(implicit EC: ExecutionContext): Future[B]
  
IO[T]
Lazy initialization, simply describes a computation
Type class instances: Effect <: Monad

fp == category theory?

Referential transparency

&

Controlled effects

"Effects are good, side-effects are bugs"
- Rob Norris

Scala 3

The age of DOT

Parallelism/Concurrency as Libraries

  • akka
  • f-p
  • scala-async
  • cats, scalaz

Scala 3

The age of DOT

  • Formalization: Dependent Object Types
  • New compiler, focus is on speed and simplicity
  • User-friendliness
  • Effect system

Effect System

  • Implicits
  • Phantom Types
def setNull[A: SetNull](a: A): A | Null = { a = null; a }

def foo(a: A) = println { setNull(a) }

def bar[A: SetNull](a: A) = {
  val a0 = setNull(a)
  a0.x // does not compile!
}

type UnsafeNull[A] =
  SetNull[A] & CanThrow[NullPointerException]

def qux[A: UnsafeNull](a: A) = {
  val a0 = setNull(a)
  a0.x
}

LaCasa

Lightweight affine types and object capabilities in Scala

F-P

Function Passing

class SparkJob {
  val theAnswer = 42

  def send = sendToOtherNode {
    heavyComputation(theAnswer)     
  }
}
class SparkJob {
  val theAnswer = 42

  def send = sendToOtherNode {
    heavyComputation(this.theAnswer)
  }
}

Conclusion

  • Types allow us to write - correct, scalable and fast code
  • Monads are cool
  • Maybe an effect system is even cooler?

Thank you!