Skip to content

Instantly share code, notes, and snippets.

@andyscott
Created April 26, 2017 23:09
Show Gist options
  • Save andyscott/ff79b75d8e07e8336cf2ad33462133df to your computer and use it in GitHub Desktop.
Save andyscott/ff79b75d8e07e8336cf2ad33462133df to your computer and use it in GitHub Desktop.
package iota_bench
import iota._
import cats._
import cats.arrow.FunctionK
import cats.data.{ State => _, _ }
import cats.free._
import org.scalacheck._
import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations._
@State(Scope.Thread)
@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
class IotaBench {
@Benchmark def iotaA: Any = Iota.evalA(Iota.genAlgebraA.sample.get)
@Benchmark def iotaB: Any = Iota.evalB(Iota.genAlgebraB.sample.get)
@Benchmark def iotaC: Any = Iota.evalC(Iota.genAlgebraC.sample.get)
@Benchmark def iotaD: Any = Iota.evalD(Iota.genAlgebraD.sample.get)
@Benchmark def iotaE: Any = Iota.evalE(Iota.genAlgebraE.sample.get)
@Benchmark def iotaF: Any = Iota.evalF(Iota.genAlgebraF.sample.get)
@Benchmark def iotaG: Any = Iota.evalG(Iota.genAlgebraG.sample.get)
@Benchmark def iotaH: Any = Iota.evalH(Iota.genAlgebraH.sample.get)
@Benchmark def iotaI: Any = Iota.evalI(Iota.genAlgebraI.sample.get)
@Benchmark def iotaJ: Any = Iota.evalJ(Iota.genAlgebraJ.sample.get)
}
object Cats {
import Ops._
type AlgebraA[A] = AOp[A]
type AlgebraB[A] = Coproduct[BOp, AlgebraA, A]
type AlgebraC[A] = Coproduct[COp, AlgebraB, A]
type AlgebraD[A] = Coproduct[DOp, AlgebraC, A]
type AlgebraE[A] = Coproduct[EOp, AlgebraD, A]
type AlgebraF[A] = Coproduct[FOp, AlgebraE, A]
type AlgebraG[A] = Coproduct[GOp, AlgebraF, A]
type AlgebraH[A] = Coproduct[HOp, AlgebraG, A]
type AlgebraI[A] = Coproduct[IOp, AlgebraH, A]
type AlgebraJ[A] = Coproduct[JOp, AlgebraI, A]
val evalA: AlgebraA ~> Id = AOp.eval
val evalB: AlgebraB ~> Id = BOp.eval or evalA
val evalC: AlgebraC ~> Id = COp.eval or evalB
val evalD: AlgebraD ~> Id = DOp.eval or evalC
val evalE: AlgebraE ~> Id = EOp.eval or evalD
val evalF: AlgebraF ~> Id = FOp.eval or evalE
val evalG: AlgebraG ~> Id = GOp.eval or evalF
val evalH: AlgebraH ~> Id = HOp.eval or evalG
val evalI: AlgebraI ~> Id = IOp.eval or evalH
val evalJ: AlgebraJ ~> Id = JOp.eval or evalI
private[this] implicit class InjectGenOps[F[_]](gf: Gen[F[_]]) {
def inj[G[_]](implicit ev: Inject[F, G]): Gen[G[_]] = gf.map(f => ev.inj(f))
}
val genAlgebraA: Gen[AlgebraA[_]] = AOp.gen.inj[AlgebraA]
val genAlgebraB: Gen[AlgebraB[_]] = AOp.gen.inj[AlgebraB]
val genAlgebraC: Gen[AlgebraC[_]] = AOp.gen.inj[AlgebraC]
val genAlgebraD: Gen[AlgebraD[_]] = AOp.gen.inj[AlgebraD]
val genAlgebraE: Gen[AlgebraE[_]] = AOp.gen.inj[AlgebraE]
val genAlgebraF: Gen[AlgebraF[_]] = AOp.gen.inj[AlgebraF]
val genAlgebraG: Gen[AlgebraG[_]] = AOp.gen.inj[AlgebraG]
val genAlgebraH: Gen[AlgebraH[_]] = AOp.gen.inj[AlgebraH]
val genAlgebraI: Gen[AlgebraI[_]] = AOp.gen.inj[AlgebraI]
val genAlgebraJ: Gen[AlgebraJ[_]] = AOp.gen.inj[AlgebraJ]
}
object Iota {
import Ops._
import KList.::
type KListA = AOp :: KNil
type AlgebraA[A] = CopK[KListA, A]
type KListB = BOp :: KListA
type AlgebraB[A] = CopK[KListB, A]
type KListC = COp :: KListB
type AlgebraC[A] = CopK[KListC, A]
type KListD = DOp :: KListC
type AlgebraD[A] = CopK[KListD, A]
type KListE = EOp :: KListD
type AlgebraE[A] = CopK[KListE, A]
type KListF = FOp :: KListE
type AlgebraF[A] = CopK[KListF, A]
type KListG = GOp :: KListF
type AlgebraG[A] = CopK[KListG, A]
type KListH = HOp :: KListG
type AlgebraH[A] = CopK[KListH, A]
type KListI = IOp :: KListH
type AlgebraI[A] = CopK[KListI, A]
type KListJ = JOp :: KListI
type AlgebraJ[A] = CopK[KListJ, A]
val evalA: AlgebraA ~> Id = CopK.FunctionK.of(AOp.eval)
val evalB: AlgebraB ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval)
val evalC: AlgebraC ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval)
val evalD: AlgebraD ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval)
val evalE: AlgebraE ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval)
val evalF: AlgebraF ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval, FOp.eval)
val evalG: AlgebraG ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval, FOp.eval, GOp.eval)
val evalH: AlgebraH ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval, FOp.eval, GOp.eval, HOp.eval)
val evalI: AlgebraI ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval, FOp.eval, GOp.eval, HOp.eval, IOp.eval)
val evalJ: AlgebraJ ~> Id = CopK.FunctionK.of(AOp.eval, BOp.eval, COp.eval, DOp.eval, EOp.eval, FOp.eval, GOp.eval, HOp.eval, IOp.eval, JOp.eval)
private[this] implicit class InjectGenOps[F[_]](gf: Gen[F[_]]) {
def inj[G[_] <: CopK[_, _]](implicit ev: CopK.Inject[F, G]): Gen[G[_]] = gf.map(f => ev.inj(f))
}
val genAlgebraA: Gen[AlgebraA[_]] = AOp.gen.inj[AlgebraA]
val genAlgebraB: Gen[AlgebraB[_]] = AOp.gen.inj[AlgebraB]
val genAlgebraC: Gen[AlgebraC[_]] = AOp.gen.inj[AlgebraC]
val genAlgebraD: Gen[AlgebraD[_]] = AOp.gen.inj[AlgebraD]
val genAlgebraE: Gen[AlgebraE[_]] = AOp.gen.inj[AlgebraE]
val genAlgebraF: Gen[AlgebraF[_]] = AOp.gen.inj[AlgebraF]
val genAlgebraG: Gen[AlgebraG[_]] = AOp.gen.inj[AlgebraG]
val genAlgebraH: Gen[AlgebraH[_]] = AOp.gen.inj[AlgebraH]
val genAlgebraI: Gen[AlgebraI[_]] = AOp.gen.inj[AlgebraI]
val genAlgebraJ: Gen[AlgebraJ[_]] = AOp.gen.inj[AlgebraJ]
}
object Ops {
sealed trait AOp[A]
object AOp {
case class Op1(v: Int) extends AOp[Int]
val eval = λ[AOp ~> Id] { case AOp.Op1(v) => v + 1 }
val gen: Gen[AOp[_]] = Gen.const(Op1(9000))
}
class AOps[F[_]](implicit inj: InjK[AOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(AOp.Op1(v)))
}
sealed trait BOp[A]
object BOp {
case class Op1(v: Int) extends BOp[Int]
val eval = λ[BOp ~> Id] { case BOp.Op1(v) => v + 1 }
val gen: Gen[BOp[_]] = Gen.const(Op1(9000))
}
class BOps[F[_]](implicit inj: InjK[BOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(BOp.Op1(v)))
}
sealed trait COp[A]
object COp {
case class Op1(v: Int) extends COp[Int]
val eval = λ[COp ~> Id] { case COp.Op1(v) => v + 1 }
val gen: Gen[COp[_]] = Gen.const(Op1(9000))
}
class COps[F[_]](implicit inj: InjK[COp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(COp.Op1(v)))
}
sealed trait DOp[A]
object DOp {
case class Op1(v: Int) extends DOp[Int]
val eval = λ[DOp ~> Id] { case DOp.Op1(v) => v + 1 }
val gen: Gen[DOp[_]] = Gen.const(Op1(9000))
}
class DOps[F[_]](implicit inj: InjK[DOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(DOp.Op1(v)))
}
sealed trait EOp[A]
object EOp {
case class Op1(v: Int) extends EOp[Int]
val eval = λ[EOp ~> Id] { case EOp.Op1(v) => v + 1 }
val gen: Gen[EOp[_]] = Gen.const(Op1(9000))
}
class EOps[F[_]](implicit inj: InjK[EOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(EOp.Op1(v)))
}
sealed trait FOp[A]
object FOp {
case class Op1(v: Int) extends FOp[Int]
val eval = λ[FOp ~> Id] { case FOp.Op1(v) => v + 1 }
val gen: Gen[FOp[_]] = Gen.const(Op1(9000))
}
class FOps[F[_]](implicit inj: InjK[FOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(FOp.Op1(v)))
}
sealed trait GOp[A]
object GOp {
case class Op1(v: Int) extends GOp[Int]
val eval = λ[GOp ~> Id] { case GOp.Op1(v) => v + 1 }
val gen: Gen[GOp[_]] = Gen.const(Op1(9000))
}
class GOps[F[_]](implicit inj: InjK[GOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(GOp.Op1(v)))
}
sealed trait HOp[A]
object HOp {
case class Op1(v: Int) extends HOp[Int]
val eval = λ[HOp ~> Id] { case HOp.Op1(v) => v + 1 }
val gen: Gen[HOp[_]] = Gen.const(Op1(9000))
}
class HOps[F[_]](implicit inj: InjK[HOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(HOp.Op1(v)))
}
sealed trait IOp[A]
object IOp {
case class Op1(v: Int) extends IOp[Int]
val eval = λ[IOp ~> Id] { case IOp.Op1(v) => v + 1 }
val gen: Gen[IOp[_]] = Gen.const(Op1(9000))
}
class IOps[F[_]](implicit inj: InjK[IOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(IOp.Op1(v)))
}
sealed trait JOp[A]
object JOp {
case class Op1(v: Int) extends JOp[Int]
val eval = λ[JOp ~> Id] { case JOp.Op1(v) => v + 1 }
val gen: Gen[JOp[_]] = Gen.const(Op1(9000))
}
class JOps[F[_]](implicit inj: InjK[JOp, F]) {
def op1(v: Int): Free[F, Int] = Free.liftF(inj(JOp.Op1(v)))
}
}
sealed abstract class InjK[F[_], G[_]] {
def inj: FunctionK[F, G]
def prj: FunctionK[G, λ[α => Option[F[α]]]]
final def apply[A](fa: F[A]): G[A] = inj(fa)
final def unapply[A](ga: G[A]): Option[F[A]] = prj(ga)
}
object InjK {
implicit def injKFromCatsInject[F[_], G[_]](
implicit ev: Inject[F, G]
): InjK[F, G] = new InjK[F, G] {
def inj = λ[F ~> G](ev.inj(_))
def prj = λ[G ~> λ[α => Option[F[α]]]](ev.prj(_))
}
implicit def injKfromCopKInj[F[_], L <: KList](
implicit ev: CopK.InjectL[F, L]
): InjK[F, CopK[L, ?]] = new InjK[F, CopK[L, ?]] {
def inj = λ[F ~> CopK[L, ?]](ev.inj(_))
def prj = λ[CopK[L, ?] ~> λ[α => Option[F[α]]]](ev.proj(_))
}
}
// fin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment