Skip to content

Instantly share code, notes, and snippets.

@yannick-cw
Created February 26, 2018 14:19
Show Gist options
  • Save yannick-cw/26e620aad6d7d1aa39458e630fce091c to your computer and use it in GitHub Desktop.
Save yannick-cw/26e620aad6d7d1aa39458e630fce091c to your computer and use it in GitHub Desktop.
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration.Duration
object FinalTaglessMath extends App {
trait Math[Container[_]] {
def value(i: Int): Container[Int]
def add(a: Container[Int], b: Container[Int]): Container[Int]
}
trait Multiplication[Container[_]] {
def multi(a: Container[Int], b: Container[Int]): Container[Int]
}
type Pure[Exp] = Exp
object PureMathInterpreter extends Math[Pure] {
def value(i: Int): Int = i
def add(a: Pure[Int], b: Pure[Int]): Int = a + b
}
object PureMultInterpreter extends Multiplication[Pure] {
def multi(a: Pure[Int], b: Pure[Int]): Pure[Int] = a * b
}
type Print[Exp] = String
object PrintInterpreter extends Math[Print] {
def value(i: Int): Print[Int] = s"val: $i"
def add(a: Print[Int], b: Print[Int]): Print[Int] = s"($a + $b)"
}
object PrintMultInterpreter extends Multiplication[Print] {
def multi(a: Print[Int], b: Print[Int]): Print[Int] = s"($a * $b)"
}
class AsyncMathInterpreter(implicit ec: ExecutionContext) extends Math[Future] {
def value(i: Int): Future[Int] = Future.successful(i)
def add(fa: Future[Int], fb: Future[Int]): Future[Int] =
for {
a <- fa
b <- fb
} yield a + b
}
class AsyncMultInterpreter(implicit ec: ExecutionContext) extends Multiplication[Future] {
def multi(fa: Future[Int], fb: Future[Int]): Future[Int] =
for {
a <- fa
b <- fb
} yield a * b
}
class Program[Container[_]](M: Math[Container], Mult: Multiplication[Container]) {
import M._
import Mult._
def calculateStuff: Container[Int] =
multi(add(value(10), value(1)), value(2))
}
println(new Program(PureMathInterpreter, PureMultInterpreter).calculateStuff)
println(new Program(PrintInterpreter, PrintMultInterpreter).calculateStuff)
import scala.concurrent.ExecutionContext.Implicits.global
println(
Await.result(new Program(new AsyncMathInterpreter(), new AsyncMultInterpreter()).calculateStuff, Duration.Inf))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment