Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursion schemes #237

Merged
merged 27 commits into from
Sep 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions kategory-core/src/main/kotlin/kategory/data/EitherT.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ package kategory
fun <C> foldR(lb: Eval<C>, f: (B, Eval<C>) -> Eval<C>, FF: Foldable<F>): Eval<C> = FF.compose(Either.foldable<A>()).foldRC(value, lb, f)

fun <G, C> traverse(f: (B) -> HK<G, C>, GA: Applicative<G>, FF: Traverse<F>): HK<G, EitherT<F, A, C>> {
val fa = ComposedTraverse(FF, Either.traverse<A>(), Either.monad<A>()).traverseC(value, f, GA)
return GA.map(fa, { EitherT(FF.map(it.lower(), { it.ev() })) })
val fa: HK<G, HK<Nested<F, EitherKindPartial<A>>, C>> = ComposedTraverse(FF, Either.traverse<A>(), Either.monad<A>()).traverseC(value, f, GA)
return GA.map(fa, { EitherT(FF.map(it.unnest(), { it.ev() })) })
}

fun combineK(y: EitherTKind<F, A, B>, MF: Monad<F>): EitherT<F, A, B> =
Expand Down
2 changes: 1 addition & 1 deletion kategory-core/src/main/kotlin/kategory/data/OptionT.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ package kategory

fun <G, B> traverse(f: (A) -> HK<G, B>, GA: Applicative<G>, FF: Traverse<F>): HK<G, OptionT<F, B>> {
val fa = ComposedTraverse(FF, Option.traverse(), Option.applicative()).traverseC(value, f, GA)
return GA.map(fa, { OptionT(FF.map(it.lower(), { it.ev() })) })
return GA.map(fa, { OptionT(FF.map(it.unnest(), { it.ev() })) })
}

fun <R> toLeft(default: () -> R, FF: Functor<F>): EitherT<F, A, R> =
Expand Down
116 changes: 60 additions & 56 deletions kategory-core/src/main/kotlin/kategory/typeclasses/Composed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,40 @@ package kategory
/**
* https://www.youtube.com/watch?v=wvSP5qYiz4Y
*/
interface ComposedType<out F, out G>
interface Nested<out F, out G>

typealias NestedType<F, G, A> = HK<Nested<F, G>, A>

typealias UnnestedType<F, G, A> = HK<F, HK<G, A>>

@Suppress("UNCHECKED_CAST")
fun <F, G, A> HK<F, HK<G, A>>.lift(): HK<ComposedType<F, G>, A> = this as HK<ComposedType<F, G>, A>
fun <F, G, A> UnnestedType<F, G, A>.nest(): NestedType<F, G, A> = this as HK<Nested<F, G>, A>

@Suppress("UNCHECKED_CAST")
fun <F, G, A, B> HK2<F, HK2<G, A, B>, HK2<G, A, B>>.liftB(): HK2<ComposedType<F, G>, A, B> = this as HK2<ComposedType<F, G>, A, B>
fun <F, G, A> NestedType<F, G, A>.unnest(): HK<F, HK<G, A>> = this as HK<F, HK<G, A>>

@Suppress("UNCHECKED_CAST")
fun <F, G, A> HK<ComposedType<F, G>, A>.lower(): HK<F, HK<G, A>> = this as HK<F, HK<G, A>>
fun <F, G, A, B> HK2<F, HK2<G, A, B>, HK2<G, A, B>>.binest(): HK2<Nested<F, G>, A, B> = this as HK2<Nested<F, G>, A, B>

@Suppress("UNCHECKED_CAST")
fun <F, G, A, B> HK2<ComposedType<F, G>, A, B>.lowerB(): HK2<F, HK2<G, A, B>, HK2<G, A, B>> = this as HK2<F, HK2<G, A, B>, HK2<G, A, B>>
fun <F, G, A, B> HK2<Nested<F, G>, A, B>.biunnest(): HK2<F, HK2<G, A, B>, HK2<G, A, B>> = this as HK2<F, HK2<G, A, B>, HK2<G, A, B>>

interface ComposedFoldable<F, G> :
Foldable<ComposedType<F, G>> {
Foldable<Nested<F, G>> {

fun FF(): Foldable<F>

fun GF(): Foldable<G>

override fun <A, B> foldL(fa: HK<ComposedType<F, G>, A>, b: B, f: (B, A) -> B): B =
FF().foldL(fa.lower(), b, { bb, aa -> GF().foldL(aa, bb, f) })
override fun <A, B> foldL(fa: HK<Nested<F, G>, A>, b: B, f: (B, A) -> B): B =
FF().foldL(fa.unnest(), b, { bb, aa -> GF().foldL(aa, bb, f) })

fun <A, B> foldLC(fa: HK<F, HK<G, A>>, b: B, f: (B, A) -> B): B = foldL(fa.lift(), b, f)
fun <A, B> foldLC(fa: HK<F, HK<G, A>>, b: B, f: (B, A) -> B): B = foldL(fa.nest(), b, f)

override fun <A, B> foldR(fa: HK<ComposedType<F, G>, A>, lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> =
FF().foldR(fa.lower(), lb, { laa, lbb -> GF().foldR(laa, lbb, f) })
override fun <A, B> foldR(fa: HK<Nested<F, G>, A>, lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> =
FF().foldR(fa.unnest(), lb, { laa, lbb -> GF().foldR(laa, lbb, f) })

fun <A, B> foldRC(fa: HK<F, HK<G, A>>, lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> = foldR(fa.lift(), lb, f)
fun <A, B> foldRC(fa: HK<F, HK<G, A>>, lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> = foldR(fa.nest(), lb, f)

companion object {
operator fun <F, G> invoke(FF: Foldable<F>, GF: Foldable<G>): ComposedFoldable<F, G> =
Expand All @@ -52,7 +56,7 @@ inline fun <F, reified G> Foldable<F>.compose(GT: Foldable<G> = foldable<G>()):
}

interface ComposedTraverse<F, G> :
Traverse<ComposedType<F, G>>,
Traverse<Nested<F, G>>,
ComposedFoldable<F, G> {

fun FT(): Traverse<F>
Expand All @@ -65,10 +69,10 @@ interface ComposedTraverse<F, G> :

override fun GF(): Foldable<G> = GT()

override fun <H, A, B> traverse(fa: HK<ComposedType<F, G>, A>, f: (A) -> HK<H, B>, HA: Applicative<H>): HK<H, HK<ComposedType<F, G>, B>> =
HA.map(FT().traverse(fa.lower(), { ga -> GT().traverse(ga, f, HA) }, HA), { it.lift() })
override fun <H, A, B> traverse(fa: HK<Nested<F, G>, A>, f: (A) -> HK<H, B>, HA: Applicative<H>): HK<H, HK<Nested<F, G>, B>> =
HA.map(FT().traverse(fa.unnest(), { ga -> GT().traverse(ga, f, HA) }, HA), { it.nest() })

fun <H, A, B> traverseC(fa: HK<F, HK<G, A>>, f: (A) -> HK<H, B>, HA: Applicative<H>): HK<H, HK<ComposedType<F, G>, B>> = traverse(fa.lift(), f, HA)
fun <H, A, B> traverseC(fa: HK<F, HK<G, A>>, f: (A) -> HK<H, B>, HA: Applicative<H>): HK<H, HK<Nested<F, G>, B>> = traverse(fa.nest(), f, HA)

companion object {
operator fun <F, G> invoke(
Expand All @@ -85,7 +89,7 @@ interface ComposedTraverse<F, G> :
}
}

inline fun <reified F, reified G> Traverse<F>.compose(GT: Traverse<G> = traverse<G>(), GA: Applicative<G> = applicative<G>()): Traverse<ComposedType<F, G>> =
inline fun <reified F, reified G> Traverse<F>.compose(GT: Traverse<G> = traverse<G>(), GA: Applicative<G> = applicative<G>()): Traverse<Nested<F, G>> =
object :
ComposedTraverse<F, G> {
override fun FT(): Traverse<F> = this@compose
Expand All @@ -95,57 +99,57 @@ inline fun <reified F, reified G> Traverse<F>.compose(GT: Traverse<G> = traverse
override fun GA(): Applicative<G> = GA
}

interface ComposedSemigroupK<F, G> : SemigroupK<ComposedType<F, G>> {
interface ComposedSemigroupK<F, G> : SemigroupK<Nested<F, G>> {

fun F(): SemigroupK<F>

override fun <A> combineK(x: HK<ComposedType<F, G>, A>, y: HK<ComposedType<F, G>, A>): HK<ComposedType<F, G>, A> = F().combineK(x.lower(), y.lower()).lift()
override fun <A> combineK(x: HK<Nested<F, G>, A>, y: HK<Nested<F, G>, A>): HK<Nested<F, G>, A> = F().combineK(x.unnest(), y.unnest()).nest()

fun <A> combineKC(x: HK<F, HK<G, A>>, y: HK<F, HK<G, A>>): HK<ComposedType<F, G>, A> = combineK(x.lift(), y.lift())
fun <A> combineKC(x: HK<F, HK<G, A>>, y: HK<F, HK<G, A>>): HK<Nested<F, G>, A> = combineK(x.nest(), y.nest())

companion object {
operator fun <F, G> invoke(SF: SemigroupK<F>): SemigroupK<ComposedType<F, G>> =
operator fun <F, G> invoke(SF: SemigroupK<F>): SemigroupK<Nested<F, G>> =
object : ComposedSemigroupK<F, G> {
override fun F(): SemigroupK<F> = SF
}
}
}

inline fun <F, G> SemigroupK<F>.compose(): SemigroupK<ComposedType<F, G>> = object : ComposedSemigroupK<F, G> {
inline fun <F, G> SemigroupK<F>.compose(): SemigroupK<Nested<F, G>> = object : ComposedSemigroupK<F, G> {
override fun F(): SemigroupK<F> = this@compose
}

interface ComposedMonoidK<F, G> : MonoidK<ComposedType<F, G>>, ComposedSemigroupK<F, G> {
interface ComposedMonoidK<F, G> : MonoidK<Nested<F, G>>, ComposedSemigroupK<F, G> {

override fun F(): MonoidK<F>

override fun <A> empty(): HK<ComposedType<F, G>, A> = F().empty<HK<G, A>>().lift()
override fun <A> empty(): HK<Nested<F, G>, A> = F().empty<HK<G, A>>().nest()

fun <A> emptyC(): HK<F, HK<G, A>> = empty<A>().lower()
fun <A> emptyC(): HK<F, HK<G, A>> = empty<A>().unnest()

companion object {
operator fun <F, G> invoke(MK: MonoidK<F>): MonoidK<ComposedType<F, G>> =
operator fun <F, G> invoke(MK: MonoidK<F>): MonoidK<Nested<F, G>> =
object : ComposedMonoidK<F, G> {
override fun F(): MonoidK<F> = MK
}
}
}

fun <F, G> MonoidK<F>.compose(): MonoidK<ComposedType<F, G>> = object : ComposedMonoidK<F, G> {
fun <F, G> MonoidK<F>.compose(): MonoidK<Nested<F, G>> = object : ComposedMonoidK<F, G> {
override fun F(): MonoidK<F> = this@compose
}

interface ComposedFunctor<F, G> : Functor<ComposedType<F, G>> {
interface ComposedFunctor<F, G> : Functor<Nested<F, G>> {
fun F(): Functor<F>

fun G(): Functor<G>

override fun <A, B> map(fa: HK<ComposedType<F, G>, A>, f: (A) -> B): HK<ComposedType<F, G>, B> = F().map(fa.lower(), { G().map(it, f) }).lift()
override fun <A, B> map(fa: HK<Nested<F, G>, A>, f: (A) -> B): HK<Nested<F, G>, B> = F().map(fa.unnest(), { G().map(it, f) }).nest()

fun <A, B> mapC(fa: HK<F, HK<G, A>>, f: (A) -> B): HK<F, HK<G, B>> = map(fa.lift(), f).lower()
fun <A, B> mapC(fa: HK<F, HK<G, A>>, f: (A) -> B): HK<F, HK<G, B>> = map(fa.nest(), f).unnest()

companion object {
operator fun <F, G> invoke(FF: Functor<F>, GF: Functor<G>): Functor<ComposedType<F, G>> =
operator fun <F, G> invoke(FF: Functor<F>, GF: Functor<G>): Functor<Nested<F, G>> =
object : ComposedFunctor<F, G> {
override fun F(): Functor<F> = FF

Expand All @@ -154,25 +158,25 @@ interface ComposedFunctor<F, G> : Functor<ComposedType<F, G>> {
}
}

inline fun <reified F, reified G> Functor<F>.compose(GF: Functor<G>): Functor<ComposedType<F, G>> = ComposedFunctor(this, GF)
inline fun <reified F, reified G> Functor<F>.compose(GF: Functor<G>): Functor<Nested<F, G>> = ComposedFunctor(this, GF)

interface ComposedApplicative<F, G> : Applicative<ComposedType<F, G>>, ComposedFunctor<F, G> {
interface ComposedApplicative<F, G> : Applicative<Nested<F, G>>, ComposedFunctor<F, G> {
override fun F(): Applicative<F>

override fun G(): Applicative<G>

override fun <A, B> map(fa: HK<ComposedType<F, G>, A>, f: (A) -> B): HK<ComposedType<F, G>, B> = ap(fa, pure(f))
override fun <A, B> map(fa: HK<Nested<F, G>, A>, f: (A) -> B): HK<Nested<F, G>, B> = ap(fa, pure(f))

override fun <A> pure(a: A): HK<ComposedType<F, G>, A> = F().pure(G().pure(a)).lift()
override fun <A> pure(a: A): HK<Nested<F, G>, A> = F().pure(G().pure(a)).nest()

override fun <A, B> ap(fa: HK<ComposedType<F, G>, A>, ff: HK<ComposedType<F, G>, (A) -> B>):
HK<ComposedType<F, G>, B> = F().ap(fa.lower(), F().map(ff.lower(), { gfa: HK<G, (A) -> B> -> { ga: HK<G, A> -> G().ap(ga, gfa) } })).lift()
override fun <A, B> ap(fa: HK<Nested<F, G>, A>, ff: HK<Nested<F, G>, (A) -> B>):
HK<Nested<F, G>, B> = F().ap(fa.unnest(), F().map(ff.unnest(), { gfa: HK<G, (A) -> B> -> { ga: HK<G, A> -> G().ap(ga, gfa) } })).nest()

fun <A, B> apC(fa: HK<F, HK<G, A>>, ff: HK<F, HK<G, (A) -> B>>): HK<F, HK<G, B>> = ap(fa.lift(), ff.lift()).lower()
fun <A, B> apC(fa: HK<F, HK<G, A>>, ff: HK<F, HK<G, (A) -> B>>): HK<F, HK<G, B>> = ap(fa.nest(), ff.nest()).unnest()

companion object {
operator fun <F, G> invoke(FF: Applicative<F>, GF: Applicative<G>)
: Applicative<ComposedType<F, G>> =
: Applicative<Nested<F, G>> =
object : ComposedApplicative<F, G> {
override fun F(): Applicative<F> = FF

Expand All @@ -181,14 +185,14 @@ interface ComposedApplicative<F, G> : Applicative<ComposedType<F, G>>, ComposedF
}
}

inline fun <reified F, reified G> Applicative<F>.compose(GA: Applicative<G> = applicative<G>()): Applicative<ComposedType<F, G>> = ComposedApplicative(this, GA)
inline fun <reified F, reified G> Applicative<F>.compose(GA: Applicative<G> = applicative<G>()): Applicative<Nested<F, G>> = ComposedApplicative(this, GA)

interface ComposedAlternative<F, G> : Alternative<ComposedType<F, G>>, ComposedApplicative<F, G>, ComposedMonoidK<F, G> {
interface ComposedAlternative<F, G> : Alternative<Nested<F, G>>, ComposedApplicative<F, G>, ComposedMonoidK<F, G> {
override fun F(): Alternative<F>

companion object {
operator fun <F, G> invoke(AF: Alternative<F>, AG: Applicative<G>)
: Alternative<ComposedType<F, G>> =
: Alternative<Nested<F, G>> =
object : ComposedAlternative<F, G> {
override fun F(): Alternative<F> = AF

Expand All @@ -197,19 +201,19 @@ interface ComposedAlternative<F, G> : Alternative<ComposedType<F, G>>, ComposedA
}
}

inline fun <reified F, reified G> Alternative<F>.compose(GA: Applicative<G> = applicative<G>()): Alternative<ComposedType<F, G>> = ComposedAlternative(this, GA)
inline fun <reified F, reified G> Alternative<F>.compose(GA: Applicative<G> = applicative<G>()): Alternative<Nested<F, G>> = ComposedAlternative(this, GA)

interface ComposedFunctorFilter<F, G> : FunctorFilter<ComposedType<F, G>>, ComposedFunctor<F, G> {
interface ComposedFunctorFilter<F, G> : FunctorFilter<Nested<F, G>>, ComposedFunctor<F, G> {

override fun F(): Functor<F>

override fun G(): FunctorFilter<G>

override fun <A, B> mapFilter(fga: HK<ComposedType<F, G>, A>, f: (A) -> Option<B>): HK<ComposedType<F, G>, B> =
F().map(fga.lower(), { G().mapFilter(it, f) }).lift()
override fun <A, B> mapFilter(fga: HK<Nested<F, G>, A>, f: (A) -> Option<B>): HK<Nested<F, G>, B> =
F().map(fga.unnest(), { G().mapFilter(it, f) }).nest()

fun <A, B> mapFilterC(fga: HK<F, HK<G, A>>, f: (A) -> Option<B>): HK<F, HK<G, B>> =
mapFilter(fga.lift(), f).lower()
mapFilter(fga.nest(), f).unnest()

companion object {
operator fun <F, G> invoke(FF: Functor<F>, FFG: FunctorFilter<G>): ComposedFunctorFilter<F, G> =
Expand All @@ -222,28 +226,28 @@ interface ComposedFunctorFilter<F, G> : FunctorFilter<ComposedType<F, G>>, Compo
}

inline fun <reified F, reified G> Functor<F>.composeFilter(FFG: FunctorFilter<G> = functorFilter()):
FunctorFilter<ComposedType<F, G>> = ComposedFunctorFilter(this, FFG)
FunctorFilter<Nested<F, G>> = ComposedFunctorFilter(this, FFG)

interface ComposedBifoldable<F, G> : Bifoldable<ComposedType<F, G>> {
interface ComposedBifoldable<F, G> : Bifoldable<Nested<F, G>> {
fun F(): Bifoldable<F>

fun G(): Bifoldable<G>

override fun <A, B, C> bifoldLeft(fab: HK2<ComposedType<F, G>, A, B>, c: C, f: (C, A) -> C, g: (C, B) -> C): C =
F().bifoldLeft(fab.lowerB(), c,
override fun <A, B, C> bifoldLeft(fab: HK2<Nested<F, G>, A, B>, c: C, f: (C, A) -> C, g: (C, B) -> C): C =
F().bifoldLeft(fab.biunnest(), c,
{ cc: C, gab: HK2<G, A, B> -> G().bifoldLeft(gab, cc, f, g) },
{ cc: C, gab: HK2<G, A, B> -> G().bifoldLeft(gab, cc, f, g) })

override fun <A, B, C> bifoldRight(fab: HK2<ComposedType<F, G>, A, B>, c: Eval<C>, f: (A, Eval<C>) -> Eval<C>, g: (B, Eval<C>) -> Eval<C>): Eval<C> =
F().bifoldRight(fab.lowerB(), c,
override fun <A, B, C> bifoldRight(fab: HK2<Nested<F, G>, A, B>, c: Eval<C>, f: (A, Eval<C>) -> Eval<C>, g: (B, Eval<C>) -> Eval<C>): Eval<C> =
F().bifoldRight(fab.biunnest(), c,
{ gab: HK2<G, A, B>, cc: Eval<C> -> G().bifoldRight(gab, cc, f, g) },
{ gab: HK2<G, A, B>, cc: Eval<C> -> G().bifoldRight(gab, cc, f, g) })

fun <A, B, C> bifoldLeftC(fab: HK2<F, HK2<G, A, B>, HK2<G, A, B>>, c: C, f: (C, A) -> C, g: (C, B) -> C): C =
bifoldLeft(fab.liftB(), c, f, g)
bifoldLeft(fab.binest(), c, f, g)

fun <A, B, C> bifoldRightC(fab: HK2<F, HK2<G, A, B>, HK2<G, A, B>>, c: Eval<C>, f: (A, Eval<C>) -> Eval<C>, g: (B, Eval<C>) -> Eval<C>): Eval<C> =
bifoldRight(fab.liftB(), c, f, g)
bifoldRight(fab.binest(), c, f, g)

companion object {
operator fun <F, G> invoke(BF: Bifoldable<F>, BG: Bifoldable<G>): ComposedBifoldable<F, G> =
Expand All @@ -255,4 +259,4 @@ interface ComposedBifoldable<F, G> : Bifoldable<ComposedType<F, G>> {
}
}

inline fun <reified F, reified G> Bifoldable<F>.compose(BG: Bifoldable<G> = bifoldable()): Bifoldable<ComposedType<F, G>> = ComposedBifoldable(this, BG)
inline fun <reified F, reified G> Bifoldable<F>.compose(BG: Bifoldable<G> = bifoldable()): Bifoldable<Nested<F, G>> = ComposedBifoldable(this, BG)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ class BifoldableTests : UnitSpec() {

val eitherComposeEither = eitherBifoldable.compose(eitherBifoldable)

testLaws(BifoldableLaws.laws(eitherComposeEither, { cf: Int -> Either.Right(Either.Right(cf)).liftB() }, Eq.any()))
testLaws(BifoldableLaws.laws(eitherComposeEither, { cf: Int -> Either.Right(Either.Right(cf)).binest() }, Eq.any()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@ typealias OptionTNel = HK<OptionTKindPartial<NonEmptyListHK>, Int>

@RunWith(KTestJUnitRunner::class)
class ComposedInstancesTest : UnitSpec() {
val EQ_OPTION_NEL: Eq<HK<ComposedType<OptionHK, NonEmptyListHK>, Int>> = Eq { a, b ->
a.lower().ev() == b.lower().ev()
val EQ_OPTION_NEL: Eq<NestedType<OptionHK, NonEmptyListHK, Int>> = Eq { a, b ->
a.unnest().ev() == b.unnest().ev()
}

val EQ_LKW_OPTION: Eq<HK<ComposedType<ListKWHK, OptionHK>, Int>> = Eq { a, b ->
a.lower().ev() == b.lower().ev()
val EQ_LKW_OPTION: Eq<NestedType<ListKWHK, OptionHK, Int>> = Eq { a, b ->
a.unnest().ev() == b.unnest().ev()
}

val EQ_OPTIONT_ID_NEL: Eq<HK<ComposedType<OptionTKindPartial<IdHK>, OptionTKindPartial<NonEmptyListHK>>, Int>> =
val EQ_OPTIONT_ID_NEL: Eq<NestedType<OptionTKindPartial<IdHK>, OptionTKindPartial<NonEmptyListHK>, Int>> =
Eq { a, b ->
a.lower().value().value().fold(
{ b.lower().value().value().isEmpty },
a.unnest().value().value().fold(
{ b.unnest().value().value().isEmpty },
{ optionA: OptionTNel ->
b.lower().value().value().ev().fold(
b.unnest().value().value().ev().fold(
{ false },
{ it.value() == optionA.value() })
})
}

val cf: (Int) -> HK<ComposedType<OptionHK, NonEmptyListHK>, Int> = { it.nel().some().lift() }
val cf: (Int) -> HK<Nested<OptionHK, NonEmptyListHK>, Int> = { it.nel().some().nest() }

init {
testLaws(FunctorLaws.laws(ComposedFunctor(Option.functor(), NonEmptyList.functor()), cf, EQ_OPTION_NEL))
testLaws(FunctorFilterLaws.laws(ComposedFunctorFilter(OptionT.functorFilter(Id.monad()), OptionT.functorFilter(NonEmptyList.monad())), { OptionT.pure(OptionT.pure(it, NonEmptyList.monad()), Id.monad()).lift() }, EQ_OPTIONT_ID_NEL))
testLaws(FunctorFilterLaws.laws(ComposedFunctorFilter(OptionT.functorFilter(Id.monad()), OptionT.functorFilter(NonEmptyList.monad())), { OptionT.pure(OptionT.pure(it, NonEmptyList.monad()), Id.monad()).nest() }, EQ_OPTIONT_ID_NEL))
testLaws(ApplicativeLaws.laws(ComposedApplicative(Option.applicative(), NonEmptyList.applicative()), EQ_OPTION_NEL))
testLaws(FoldableLaws.laws(ComposedFoldable(Option.foldable(), NonEmptyList.foldable()), cf, Eq.any()))
testLaws(TraverseLaws.laws(ComposedTraverse(Option.traverse(), NonEmptyList.traverse(), NonEmptyList.applicative()), ComposedFunctor.invoke(Option.functor(), NonEmptyList.functor()), cf, EQ_OPTION_NEL))
Expand Down
5 changes: 5 additions & 0 deletions kategory-recursion/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Recursion schemes for Kategory

This package is complex and highly experimental.

Do not use.
3 changes: 2 additions & 1 deletion kategory-recursion/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies {
testCompile project(':kategory-test')
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
// FIXME(paco): re-enable when it's prod-ready
//apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
apply from: 'generated-kotlin-sources.gradle'
apply plugin: 'kotlin-kapt'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package kategory

@higherkind data class EnvT<out B, out W, out A>(val ask: B, val lower: HK<W, A>) : EnvTKind<B, W, A>
Loading