Skip to content

Instantly share code, notes, and snippets.

@Leammas
Created February 9, 2017 10:19
Show Gist options
  • Save Leammas/48f40de728b3c536ded2c3629367e058 to your computer and use it in GitHub Desktop.
Save Leammas/48f40de728b3c536ded2c3629367e058 to your computer and use it in GitHub Desktop.
import cats.free.Free
import cats.{Id, ~>}
import freek._
object freekfoo extends App {
sealed trait CRUD[A]
case class Create(a: Foo) extends CRUD[Int]
case class Read(id: Int) extends CRUD[Foo]
case class Update(a: Foo) extends CRUD[Unit]
case class Delete(id: Int) extends CRUD[Unit]
case class Foo(id: Int, content: String)
sealed trait Sum[A]
case class ConcatFoo(a: Foo, b: Foo) extends Sum[Foo]
case class SumFoo(a: Foo, b: Foo) extends Sum[Foo]
type PRG = Sum :|: CRUD :|: NilDSL
val PRG = DSL.Make[PRG]
def program: (Foo) => Free[PRG.Cop, List[Foo]] = f => {
for {
id <- Create(f).freek[PRG]
created <- Read(id).freek[PRG]
_ <- Update(created.copy(content = "bar")).freek[PRG]
updated <- Read(id).freek[PRG]
concated <- ConcatFoo(created, updated).freek[PRG]
summed <- SumFoo(created, updated).freek[PRG]
} yield List(concated, summed)
}
object InterpreterId extends (CRUD ~> Id) {
var store = Map.empty[Int, Foo]
var ai = 1
def apply[A](fa: CRUD[A]): Id[A] = fa match {
case Create(a) =>
val aId = a.copy(id = ai)
store = store + (ai -> aId)
ai = ai + 1
aId.id
case Read(id) =>
store(id)
case Update(a) =>
store = store.updated(a.id, a)
()
case Delete(id) =>
store = store - id
()
}
}
object ISumId extends (Sum ~> Id) {
def apply[A](fa: Sum[A]): Id[A] = fa match {
case ConcatFoo(a, b) => Foo(a.id, a.content + b.content)
case SumFoo(a, b) => Foo(a.id + b.id, a.content)
}
}
val interpreter = InterpreterId :&: ISumId
val toRun = program(Foo(-100, "content"))
assert {
toRun.interpret(interpreter) == List(Foo(1, "contentbar"), Foo(2, "content"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment