package arrow.typeclasses import arrow.Kind import arrow.core.Either import arrow.core.Eval import arrow.core.Tuple2 import arrow.core.identity import kotlin.coroutines.startCoroutine interface Monad<F> : Applicative<F> { fun <A, B> Kind<F, A>.flatMap(f: (A) -> Kind<F, B>): Kind<F, B> fun <A, B> tailRecM(a: A, f: (A) -> Kind<F, Either<A, B>>): Kind<F, B> override fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> = flatMap { a -> just(f(a)) } override fun <A, B> Kind<F, A>.ap(ff: Kind<F, (A) -> B>): Kind<F, B> = ff.flatMap { f -> this.map(f) } fun <A> Kind<F, Kind<F, A>>.flatten(): Kind<F, A> = flatMap(::identity) fun <A, B> Kind<F, A>.followedBy(fb: Kind<F, B>): Kind<F, B> = flatMap { fb } fun <A, B> Kind<F, A>.followedByEval(fb: Eval<Kind<F, B>>): Kind<F, B> = flatMap { fb.value() } fun <A, B> Kind<F, A>.effectM(f: (A) -> Kind<F, B>): Kind<F, A> = flatMap { a -> f(a).map { a } } fun <A, B> Kind<F, A>.forEffect(fb: Kind<F, B>): Kind<F, A> = flatMap { a -> fb.map { a } } fun <A, B> Kind<F, A>.forEffectEval(fb: Eval<Kind<F, B>>): Kind<F, A> = flatMap { a -> fb.value().map { a } } fun <A, B> Kind<F, A>.mproduct(f: (A) -> Kind<F, B>): Kind<F, Tuple2<A, B>> = flatMap { a -> f(a).map { Tuple2(a, it) } } fun <B> Kind<F, Boolean>.ifM(ifTrue: () -> Kind<F, B>, ifFalse: () -> Kind<F, B>): Kind<F, B> = flatMap { if (it) ifTrue() else ifFalse() } } /** * Entry point for monad bindings which enables for comprehension. The underlying implementation is based on coroutines. * A coroutine is initiated and suspended inside [MonadErrorContinuation] yielding to [Monad.flatMap]. Once all the flatMap binds are completed * the underlying monad is returned from the act of executing the coroutine */ fun <F, B> Monad<F>.binding(c: suspend MonadContinuation<F, *>.() -> B): Kind<F, B> { val continuation = MonadContinuation<F, B>(this) val wrapReturn: suspend MonadContinuation<F, *>.() -> Kind<F, B> = { just(c()) } wrapReturn.startCoroutine(continuation, continuation) return continuation.returnedMonad() }
往背後看源代碼:
package arrow interface Kind<out F, out A> typealias Kind2<F, A, B> = Kind<Kind<F, A>, B> typealias Kind3<F, A, B, C> = Kind<Kind2<F, A, B>, C> typealias Kind4<F, A, B, C, D> = Kind<Kind3<F, A, B, C>, D> typealias Kind5<F, A, B, C, D, E> = Kind<Kind4<F, A, B, C, D>, E> typealias Kind6<F, A, B, C, D, E, G> = Kind<Kind5<F, A, B, C, D, E>, G> typealias Kind7<F, A, B, C, D, E, G, H> = Kind<Kind6<F, A, B, C, D, E, G>, H> typealias Kind8<F, A, B, C, D, E, G, H, I> = Kind<Kind7<F, A, B, C, D, E, G, H>, I> typealias Kind9<F, A, B, C, D, E, G, H, I, J> = Kind<Kind8<F, A, B, C, D, E, G, H, I>, J> typealias Kind10<F, A, B, C, D, E, G, H, I, J, K> = Kind<Kind9<F, A, B, C, D, E, G, H, I, J>, K> typealias Kind11<F, A, B, C, D, E, G, H, I, J, K, L> = Kind<Kind10<F, A, B, C, D, E, G, H, I, J, K>, L> typealias Kind12<F, A, B, C, D, E, G, H, I, J, K, L, M> = Kind<Kind11<F, A, B, C, D, E, G, H, I, J, K, L>, M> typealias Kind13<F, A, B, C, D, E, G, H, I, J, K, L, M, N> = Kind<Kind12<F, A, B, C, D, E, G, H, I, J, K, L, M>, N> typealias Kind14<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O> = Kind<Kind13<F, A, B, C, D, E, G, H, I, J, K, L, M, N>, O> typealias Kind15<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P> = Kind<Kind14<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O>, P> typealias Kind16<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q> = Kind<Kind15<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P>, Q> typealias Kind17<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R> = Kind<Kind16<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q>, R> typealias Kind18<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S> = Kind<Kind17<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R>, S> typealias Kind19<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T> = Kind<Kind18<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S>, T> typealias Kind20<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U> = Kind<Kind19<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T>, U> typealias Kind21<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V> = Kind<Kind20<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U>, V> typealias Kind22<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W> = Kind<Kind21<F, A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V>, W> package arrow.typeclasses import arrow.Kind interface Invariant<F> { fun <A, B> Kind<F, A>.imap(f: (A) -> B, g: (B) -> A): Kind<F, B> } package arrow.typeclasses import arrow.Kind import arrow.core.Tuple2 interface Functor<F> : Invariant<F> { fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> override fun <A, B> Kind<F, A>.imap(f: (A) -> B, g: (B) -> A): Kind<F, B> = map(f) fun <A, B> lift(f: (A) -> B): (Kind<F, A>) -> Kind<F, B> = { fa: Kind<F, A> -> fa.map(f) } fun <A> Kind<F, A>.void(): Kind<F, Unit> = map { _ -> Unit } fun <A, B> Kind<F, A>.fproduct(f: (A) -> B): Kind<F, Tuple2<A, B>> = map { a -> Tuple2(a, f(a)) } fun <A, B> Kind<F, A>.`as`(b: B): Kind<F, B> = map { _ -> b } fun <A, B> Kind<F, A>.tupleLeft(b: B): Kind<F, Tuple2<B, A>> = map { a -> Tuple2(b, a) } fun <A, B> Kind<F, A>.tupleRight(b: B): Kind<F, Tuple2<A, B>> = map { a -> Tuple2(a, b) } fun <B, A : B> Kind<F, A>.widen(): Kind<F, B> = this } @file:Suppress("UNUSED_PARAMETER") package arrow.typeclasses import arrow.Kind import arrow.core.* import java.math.BigDecimal interface Applicative<F> : Functor<F> { fun <A> just(a: A): Kind<F, A> fun <A> A.just(dummy: Unit = Unit): Kind<F, A> = just(this) fun <A, B> Kind<F, A>.ap(ff: Kind<F, (A) -> B>): Kind<F, B> fun <A, B> Kind<F, A>.product(fb: Kind<F, B>): Kind<F, Tuple2<A, B>> = fb.ap(this.map { a: A -> { b: B -> Tuple2(a, b) } }) override fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> = ap(just(f)) fun <A, B, Z> Kind<F, A>.map2(fb: Kind<F, B>, f: (Tuple2<A, B>) -> Z): Kind<F, Z> = product(fb).map(f) fun <A, B, Z> Kind<F, A>.map2Eval(fb: Eval<Kind<F, B>>, f: (Tuple2<A, B>) -> Z): Eval<Kind<F, Z>> = fb.map { fc -> map2(fc, f) } fun <A, B, Z> Kind<F, Tuple2<A, B>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit): Kind<F, Tuple3<A, B, Z>> = other.product(this).map { Tuple3(it.b.a, it.b.b, it.a) } fun <A, B, C, Z> Kind<F, Tuple3<A, B, C>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit): Kind<F, Tuple4<A, B, C, Z>> = other.product(this).map { Tuple4(it.b.a, it.b.b, it.b.c, it.a) } fun <A, B, C, D, Z> Kind<F, Tuple4<A, B, C, D>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit): Kind<F, Tuple5<A, B, C, D, Z>> = other.product(this).map { Tuple5(it.b.a, it.b.b, it.b.c, it.b.d, it.a) } fun <A, B, C, D, E, Z> Kind<F, Tuple5<A, B, C, D, E>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit, dummyImplicit4: Unit = Unit): Kind<F, Tuple6<A, B, C, D, E, Z>> = other.product(this).map { Tuple6(it.b.a, it.b.b, it.b.c, it.b.d, it.b.e, it.a) } fun <A, B, C, D, E, FF, Z> Kind<F, Tuple6<A, B, C, D, E, FF>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit, dummyImplicit4: Unit = Unit, dummyImplicit5: Unit = Unit): Kind<F, Tuple7<A, B, C, D, E, FF, Z>> = other.product(this).map { Tuple7(it.b.a, it.b.b, it.b.c, it.b.d, it.b.e, it.b.f, it.a) } fun <A, B, C, D, E, FF, G, Z> Kind<F, Tuple7<A, B, C, D, E, FF, G>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit, dummyImplicit4: Unit = Unit, dummyImplicit5: Unit = Unit, dummyImplicit6: Unit = Unit): Kind<F, Tuple8<A, B, C, D, E, FF, G, Z>> = other.product(this).map { Tuple8(it.b.a, it.b.b, it.b.c, it.b.d, it.b.e, it.b.f, it.b.g, it.a) } fun <A, B, C, D, E, FF, G, H, Z> Kind<F, Tuple8<A, B, C, D, E, FF, G, H>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit, dummyImplicit4: Unit = Unit, dummyImplicit5: Unit = Unit, dummyImplicit6: Unit = Unit, dummyImplicit7: Unit = Unit): Kind<F, Tuple9<A, B, C, D, E, FF, G, H, Z>> = other.product(this).map { Tuple9(it.b.a, it.b.b, it.b.c, it.b.d, it.b.e, it.b.f, it.b.g, it.b.h, it.a) } fun <A, B, C, D, E, FF, G, H, I, Z> Kind<F, Tuple9<A, B, C, D, E, FF, G, H, I>>.product( other: Kind<F, Z>, dummyImplicit: Unit = Unit, dummyImplicit2: Unit = Unit, dummyImplicit3: Unit = Unit, dummyImplicit4: Unit = Unit, dummyImplicit5: Unit = Unit, dummyImplicit6: Unit = Unit, dummyImplicit7: Unit = Unit, dummyImplicit9: Unit = Unit): Kind<F, Tuple10<A, B, C, D, E, FF, G, H, I, Z>> = other.product(this).map { Tuple10(it.b.a, it.b.b, it.b.c, it.b.d, it.b.e, it.b.f, it.b.g, it.b.h, it.b.i, it.a) } fun <A, B> tupled( a: Kind<F, A>, b: Kind<F, B>): Kind<F, Tuple2<A, B>> = a.product(b) fun <A, B, C> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>): Kind<F, Tuple3<A, B, C>> = a.product(b).product(c) fun <A, B, C, D> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>): Kind<F, Tuple4<A, B, C, D>> = a.product(b).product(c).product(d) fun <A, B, C, D, E> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>): Kind<F, Tuple5<A, B, C, D, E>> = a.product(b).product(c).product(d).product(e) fun <A, B, C, D, E, FF> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>): Kind<F, Tuple6<A, B, C, D, E, FF>> = a.product(b).product(c).product(d).product(e).product(f) fun <A, B, C, D, E, FF, G> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>): Kind<F, Tuple7<A, B, C, D, E, FF, G>> = a.product(b).product(c).product(d).product(e).product(f).product(g) fun <A, B, C, D, E, FF, G, H> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>): Kind<F, Tuple8<A, B, C, D, E, FF, G, H>> = a.product(b).product(c).product(d).product(e).product(f).product(g).product(h) fun <A, B, C, D, E, FF, G, H, I> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>, i: Kind<F, I>): Kind<F, Tuple9<A, B, C, D, E, FF, G, H, I>> = a.product(b).product(c).product(d).product(e).product(f).product(g).product(h).product(i) fun <A, B, C, D, E, FF, G, H, I, J> tupled( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>, i: Kind<F, I>, j: Kind<F, J>): Kind<F, Tuple10<A, B, C, D, E, FF, G, H, I, J>> = a.product(b).product(c).product(d).product(e).product(f).product(g) .product(h).product(i).product(j) fun <A, B, Z> map( a: Kind<F, A>, b: Kind<F, B>, lbd: (Tuple2<A, B>) -> Z): Kind<F, Z> = a.product(b).map(lbd) fun <A, B, C, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, lbd: (Tuple3<A, B, C>) -> Z): Kind<F, Z> = a.product(b).product(c).map(lbd) fun <A, B, C, D, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, lbd: (Tuple4<A, B, C, D>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).map(lbd) fun <A, B, C, D, E, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, lbd: (Tuple5<A, B, C, D, E>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).map(lbd) fun <A, B, C, D, E, FF, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, lbd: (Tuple6<A, B, C, D, E, FF>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).product(f).map(lbd) operator fun Kind<F, BigDecimal>.plus(other: Kind<F, BigDecimal>): Kind<F, BigDecimal> = map(this, other) { (a, b) -> a + b } fun <A, B, C, D, E, FF, G, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, lbd: (Tuple7<A, B, C, D, E, FF, G>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).product(f).product(g).map(lbd) fun <A, B, C, D, E, FF, G, H, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>, lbd: (Tuple8<A, B, C, D, E, FF, G, H>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).product(f) .product(g).product(h).map(lbd) fun <A, B, C, D, E, FF, G, H, I, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>, i: Kind<F, I>, lbd: (Tuple9<A, B, C, D, E, FF, G, H, I>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).product(f) .product(g).product(h).product(i).map(lbd) fun <A, B, C, D, E, FF, G, H, I, J, Z> map( a: Kind<F, A>, b: Kind<F, B>, c: Kind<F, C>, d: Kind<F, D>, e: Kind<F, E>, f: Kind<F, FF>, g: Kind<F, G>, h: Kind<F, H>, i: Kind<F, I>, j: Kind<F, J>, lbd: (Tuple10<A, B, C, D, E, FF, G, H, I, J>) -> Z): Kind<F, Z> = a.product(b).product(c).product(d).product(e).product(f) .product(g).product(h).product(i).product(j).map(lbd) }