Created
April 26, 2017 23:09
-
-
Save andyscott/ff79b75d8e07e8336cf2ad33462133df to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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