app.cash.quiver.extensions.Ior.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lib Show documentation
Show all versions of lib Show documentation
Quiver library providing extension methods and type aliases to improve Arrow
The newest version!
package app.cash.quiver.extensions
import arrow.core.Either
import arrow.core.Ior
import arrow.core.Ior.Both
import arrow.core.Ior.Left
import arrow.core.Ior.Right
import arrow.core.None
import arrow.core.Option
import arrow.core.Some
import arrow.core.some
import kotlin.experimental.ExperimentalTypeInference
import app.cash.quiver.extensions.traverse as quiverTraverse
@PublishedApi
internal val unitIor: Ior = Right(Unit)
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
map: (B, C) -> D
): Ior =
zip(
combine,
c,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor
) { b, cc, _, _, _, _, _, _, _, _ -> map(b, cc) }
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
map: (B, C, D) -> E
): Ior =
zip(
combine,
c,
d,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor
) { b, cc, dd, _, _, _, _, _, _, _ -> map(b, cc, dd) }
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
map: (B, C, D, E) -> F
): Ior =
zip(
combine,
c,
d,
e,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor,
unitIor
) { b, cc, dd, ee, _, _, _, _, _, _ -> map(b, cc, dd, ee) }
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
map: (B, C, D, E, F) -> G
): Ior =
zip(combine, c, d, e, f, unitIor, unitIor, unitIor, unitIor, unitIor) { b, cc, dd, ee, ff, _, _, _, _, _ ->
map(
b,
cc,
dd,
ee,
ff
)
}
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
g: Ior,
map: (B, C, D, E, F, G) -> H
): Ior =
zip(combine, c, d, e, f, g, unitIor, unitIor, unitIor, unitIor) { b, cc, dd, ee, ff, gg, _, _, _, _ ->
map(
b,
cc,
dd,
ee,
ff,
gg
)
}
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
g: Ior,
h: Ior,
map: (B, C, D, E, F, G, H) -> I
): Ior =
zip(combine, c, d, e, f, g, h, unitIor, unitIor, unitIor) { b, cc, dd, ee, ff, gg, hh, _, _, _ ->
map(
b,
cc,
dd,
ee,
ff,
gg,
hh
)
}
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
g: Ior,
h: Ior,
i: Ior,
map: (B, C, D, E, F, G, H, I) -> J
): Ior =
zip(combine, c, d, e, f, g, h, i, unitIor, unitIor) { b, cc, dd, ee, ff, gg, hh, ii, _, _ ->
map(
b,
cc,
dd,
ee,
ff,
gg,
hh,
ii
)
}
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
g: Ior,
h: Ior,
i: Ior,
j: Ior,
map: (B, C, D, E, F, G, H, I, J) -> K
): Ior =
zip(combine, c, d, e, f, g, h, i, j, unitIor) { b, cc, dd, ee, ff, gg, hh, ii, jj, _ ->
map(
b,
cc,
dd,
ee,
ff,
gg,
hh,
ii,
jj
)
}
@Suppress("UNCHECKED_CAST")
inline fun Ior.zip(
crossinline combine: (A, A) -> A,
c: Ior,
d: Ior,
e: Ior,
f: Ior,
g: Ior,
h: Ior,
i: Ior,
j: Ior,
k: Ior,
transform: (B, C, D, E, F, G, H, I, J, K) -> L
): Ior {
val right: Option = if (
([email protected]() || [email protected]()) &&
(c.isRight() || c.isBoth()) &&
(d.isRight() || d.isBoth()) &&
(e.isRight() || e.isBoth()) &&
(f.isRight() || f.isBoth()) &&
(g.isRight() || g.isBoth()) &&
(h.isRight() || h.isBoth()) &&
(i.isRight() || i.isBoth()) &&
(j.isRight() || j.isBoth()) &&
(k.isRight() || k.isBoth())
) {
transform(
[email protected]() as B,
c.getOrNull() as C,
d.getOrNull() as D,
e.getOrNull() as E,
f.getOrNull() as F,
g.getOrNull() as G,
h.getOrNull() as H,
i.getOrNull() as I,
j.getOrNull() as J,
k.getOrNull() as K
).some()
} else None
var left: Option = None
if (this@zip is Left) return@zip Left([email protected])
left = if (this@zip is Both) Some([email protected]) else left
if (c is Left) return@zip Left(left.emptyCombine(c.value, combine))
left = if (c is Both) Some(left.emptyCombine(c.leftValue, combine)) else left
if (d is Left) return@zip Left(left.emptyCombine(d.value, combine))
left = if (d is Both) Some(left.emptyCombine(d.leftValue, combine)) else left
if (e is Left) return@zip Left(left.emptyCombine(e.value, combine))
left = if (e is Both) Some(left.emptyCombine(e.leftValue, combine)) else left
if (f is Left) return@zip Left(left.emptyCombine(f.value, combine))
left = if (f is Both) Some(left.emptyCombine(f.leftValue, combine)) else left
if (g is Left) return@zip Left(left.emptyCombine(g.value, combine))
left = if (g is Both) Some(left.emptyCombine(g.leftValue, combine)) else left
if (h is Left) return@zip Left(left.emptyCombine(h.value, combine))
left = if (h is Both) Some(left.emptyCombine(h.leftValue, combine)) else left
if (i is Left) return@zip Left(left.emptyCombine(i.value, combine))
left = if (i is Both) Some(left.emptyCombine(i.leftValue, combine)) else left
if (j is Left) return@zip Left(left.emptyCombine(j.value, combine))
left = if (j is Both) Some(left.emptyCombine(j.leftValue, combine)) else left
if (k is Left) return@zip Left(left.emptyCombine(k.value, combine))
left = if (k is Both)Some(left.emptyCombine(k.leftValue, combine)) else left
return when(right) {
is Some -> when(left) {
is Some -> Both(left.value, right.value)
is None -> Right(right.value)
}
None -> when(left) {
is Some -> Left(left.value)
is None -> throw IllegalStateException("Ior.zip should not be possible to reach this state")
}
}
}
@PublishedApi
internal inline fun Option.emptyCombine(other: A, combine: (A, A) -> A): A =
when (this) {
is Some -> combine(this.value, other)
is None -> other
}
@OptIn(ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun Ior.traverse(f: (B) -> Either): Either> =
fold(
{ a -> Either.Right(Left(a)) },
{ b -> f(b).map { Right(it) } },
{ a, b -> f(b).map { Both(a, it) } }
)
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun Ior.traverseEither(f: (B) -> Either): Either> =
quiverTraverse(f)
@OptIn(ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun Ior.traverse(f: (B) -> Option): Option> =
fold(
{ a -> Some(Left(a)) },
{ b -> f(b).map { Right(it) } },
{ a, b -> f(b).map { Both(a, it) } }
)
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun Ior.traverseOption(f: (B) -> Option): Option> =
quiverTraverse(f)
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
inline fun Ior.traverse(f: (B) -> Iterable): List> =
fold(
{ a -> listOf(Left(a)) },
{ b -> f(b).map { Right(it) } },
{ a, b -> f(b).map { Both(a, it) } }
)