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
}
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