diff --git a/src/main/kotlin/io/github/aedans/katalyst/Recursion.kt b/src/main/kotlin/io/github/aedans/katalyst/Recursion.kt index 72717b9..af58f4d 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/Recursion.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/Recursion.kt @@ -22,10 +22,10 @@ typealias Coalgebra = (A) -> Kind * The composition of cata and ana. */ fun hylo( - a: A, + FF: Functor, alg: Algebra>, coalg: Coalgebra, - FF: Functor + a: A ): B = FF.run { fun h(a: A): Eval = alg(coalg(a).map { Eval.defer { h(it) } }) return h(a).value() diff --git a/src/main/kotlin/io/github/aedans/katalyst/data/Fix.kt b/src/main/kotlin/io/github/aedans/katalyst/data/Fix.kt index 9f8a66b..e6e926b 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/data/Fix.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/data/Fix.kt @@ -16,11 +16,11 @@ data class Fix(val unfix: Kind>>) : FixOf { @instance(Fix::class) interface FixBirecursiveInstance : Birecursive { - override fun projectT(t: FixOf, FF: Functor) = FF.run { + override fun projectT(FF: Functor, t: FixOf) = FF.run { t.fix().unfix.map { it.value() } } - override fun embedT(t: Kind>>, FF: Functor) = + override fun embedT(FF: Functor, t: Kind>>) = Eval.later { Fix(t) } } diff --git a/src/main/kotlin/io/github/aedans/katalyst/data/Mu.kt b/src/main/kotlin/io/github/aedans/katalyst/data/Mu.kt index f8f001a..9eedf5a 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/data/Mu.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/data/Mu.kt @@ -19,24 +19,24 @@ abstract class Mu : MuOf { @instance(Mu::class) interface MuBirecursiveInstance : Birecursive { - override fun embedT(t: Kind>>, FF: Functor): Eval> = FF.run { + override fun embedT(FF: Functor, t: Kind>>): Eval> = FF.run { Eval.now(object : Mu() { override fun unMu(fa: Algebra>) = fa(t.map { it.flatMap { it.fix().unMu(fa) } }) }) } - override fun projectT(t: MuOf, FF: Functor): Kind> = FF.run { - t.cata({ ff -> + override fun projectT(FF: Functor, t: MuOf): Kind> = FF.run { + t.cata(FF, { ff -> Eval.later { ff.map { f -> - embedT(f.value().map(::Now), FF).value() + embedT(FF, f.value().map(::Now)).value() } } - }, FF) + }) } - override fun MuOf.cata(alg: Algebra>, FF: Functor): A = + override fun MuOf.cata(FF: Functor, alg: Algebra>): A = fix().unMu(alg).value() } diff --git a/src/main/kotlin/io/github/aedans/katalyst/data/Nu.kt b/src/main/kotlin/io/github/aedans/katalyst/data/Nu.kt index baa2bc6..d17ce14 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/data/Nu.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/data/Nu.kt @@ -22,17 +22,17 @@ class Nu(val a: Any?, val unNu: Coalgebra) : NuOf { @instance(Nu::class) interface NuBirecursiveInstance : Birecursive { - override fun projectT(t: NuOf, FF: Functor): Kind> = FF.run { + override fun projectT(FF: Functor, t: NuOf): Kind> = FF.run { val fix = t.fix() val unNu = fix.unNu unNu(fix.a).map { Nu(it, unNu) } } - override fun embedT(t: Kind>>, FF: Functor) = FF.run { - Eval.now(Nu.invoke(t) { f -> f.map { nu -> projectT(nu.value(), FF).map(::Now) } }) + override fun embedT(FF: Functor, t: Kind>>) = FF.run { + Eval.now(Nu.invoke(t) { f -> f.map { nu -> projectT(FF, nu.value()).map(::Now) } }) } - override fun A.ana(coalg: Coalgebra, FF: Functor) = + override fun A.ana(FF: Functor, coalg: Coalgebra) = Nu(this, coalg) } diff --git a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/List.kt b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/List.kt index 6809bb4..b286b0a 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/List.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/List.kt @@ -42,9 +42,9 @@ fun fromGListAlgebra() = Algebra, Eval>> { } inline fun List.toGList(CT: Corecursive): GList = CT.run { - ana(toGListCoalgebra(), ComposedFunctor(Option.functor(), Tuple2.functor())) + ana(ComposedFunctor(Option.functor(), Tuple2.functor()), toGListCoalgebra()) } inline fun GList.toCofree(RT: Recursive): List = RT.run { - cata(fromGListAlgebra(), ComposedFunctor(Option.functor(), Tuple2.functor())) + cata(ComposedFunctor(Option.functor(), Tuple2.functor()), fromGListAlgebra()) } diff --git a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/Nat.kt b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/Nat.kt index 6b68bcf..8bb91b1 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/Nat.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/Nat.kt @@ -27,9 +27,9 @@ fun fromGNatAlgebra() = Algebra> { } inline fun Int.toGNat(CT: Corecursive): GNat = CT.run { - ana(toGNatCoalgebra(), Option.functor()) + ana(Option.functor(), toGNatCoalgebra()) } inline fun GNat.toInt(RT: Recursive): Int = RT.run { - cata(fromGNatAlgebra(), Option.functor()) + cata(Option.functor(), fromGNatAlgebra()) } diff --git a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/NonEmptyList.kt b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/NonEmptyList.kt index 185648b..752d0fe 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/NonEmptyList.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/fixedpoint/NonEmptyList.kt @@ -4,7 +4,6 @@ import arrow.Kind import arrow.core.* import arrow.data.NonEmptyList import arrow.data.nel -import arrow.syntax.collections.prependTo import arrow.typeclasses.ComposedFunctor import arrow.typeclasses.Nested import arrow.typeclasses.nest @@ -44,9 +43,9 @@ fun fromGNonEmptyListAlgebra() = Algebra, Eval List.toGNonEmptyList(CT: Corecursive): GList = CT.run { - ana(toGListCoalgebra(), ComposedFunctor(Option.functor(), Tuple2.functor())) + ana(ComposedFunctor(Option.functor(), Tuple2.functor()), toGListCoalgebra()) } inline fun GList.toNonEmptyList(RT: Recursive): List = RT.run { - cata(fromGListAlgebra(), ComposedFunctor(Option.functor(), Tuple2.functor())) + cata(ComposedFunctor(Option.functor(), Tuple2.functor()), fromGListAlgebra()) } diff --git a/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Corecursive.kt b/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Corecursive.kt index 85cf994..9820e58 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Corecursive.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Corecursive.kt @@ -14,15 +14,15 @@ interface Corecursive { /** * Implementation for embed. */ - fun embedT(t: Kind>>, FF: Functor): Eval> + fun embedT(FF: Functor, t: Kind>>): Eval> /** * Creates a algebra given a functor. */ - fun embed(FF: Functor): Algebra>> = { embedT(it, FF) } + fun embed(FF: Functor): Algebra>> = { embedT(FF, it) } /** * Unfold into any recursive type. */ - fun A.ana(coalg: Coalgebra, FF: Functor): Kind = hylo(this, embed(FF), coalg, FF) + fun A.ana(FF: Functor, coalg: Coalgebra): Kind = hylo(FF, embed(FF), coalg, this) } diff --git a/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Recursive.kt b/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Recursive.kt index 857b692..356204d 100644 --- a/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Recursive.kt +++ b/src/main/kotlin/io/github/aedans/katalyst/typeclasses/Recursive.kt @@ -14,17 +14,17 @@ interface Recursive { /** * Implementation for project. */ - fun projectT(t: Kind, FF: Functor): Kind> + fun projectT(FF: Functor, t: Kind): Kind> /** * Creates a coalgebra given a functor. */ fun project(FF: Functor): Coalgebra> = - { projectT(it, FF) } + { projectT(FF, it) } /** * Fold generalized over any recursive type. */ - fun Kind.cata(alg: Algebra>, FF: Functor): A = - hylo(this, alg, project(FF), FF) + fun Kind.cata(FF: Functor, alg: Algebra>): A = + hylo(FF, alg, project(FF), this) } diff --git a/src/test/kotlin/io/github/aedans/katalyst/examples/Expr.kt b/src/test/kotlin/io/github/aedans/katalyst/examples/Expr.kt index d9ae28c..fae38bb 100644 --- a/src/test/kotlin/io/github/aedans/katalyst/examples/Expr.kt +++ b/src/test/kotlin/io/github/aedans/katalyst/examples/Expr.kt @@ -53,7 +53,7 @@ fun evalExprAlgebra() = Algebra> { fun main(args: Array) { val expr = plus(plus(int(1), int(2)), neg(plus(int(3), int(4)))) Fix.recursive().run { - expr.cata(evalExprAlgebra(), ExprPattern.functor()) // -4 + expr.cata(ExprPattern.functor(), evalExprAlgebra()) // -4 } } @@ -65,7 +65,7 @@ class ExprTest : UnitSpec() { "expr.cata(alg = evalExprAlgebra()) should be -4" { Fix.recursive().run { - expr.cata(evalExprAlgebra(), ExprPattern.functor()) + expr.cata(ExprPattern.functor(), evalExprAlgebra()) } shouldEqual -4 } } diff --git a/src/test/kotlin/io/github/aedans/katalyst/laws/BirecursiveLaws.kt b/src/test/kotlin/io/github/aedans/katalyst/laws/BirecursiveLaws.kt index d811808..90f0728 100644 --- a/src/test/kotlin/io/github/aedans/katalyst/laws/BirecursiveLaws.kt +++ b/src/test/kotlin/io/github/aedans/katalyst/laws/BirecursiveLaws.kt @@ -14,14 +14,14 @@ object BirecursiveLaws { Law("Birecursive Laws: ana . cata == hylo") { forAll(intGen) { val composed = it - .ana(toGNatCoalgebra(), Option.functor()) - .cata(fromGNatAlgebra(), Option.functor()) - val hylo = hylo(it, fromGNatAlgebra(), toGNatCoalgebra(), Option.functor()) + .ana(Option.functor(), toGNatCoalgebra()) + .cata(Option.functor(), fromGNatAlgebra()) + val hylo = hylo(Option.functor(), fromGNatAlgebra(), toGNatCoalgebra(), it) hylo == composed } }, Law("Birecursive Laws: Stack-safe cata, ana, and hylo") { - 100000.toGNat(BT).cata(fromGNatAlgebra(), Option.functor()) shouldEqual 100000 + 100000.toGNat(BT).cata(Option.functor(), fromGNatAlgebra()) shouldEqual 100000 } ) }