All Downloads are FREE. Search and download functionalities are using the official Maven repository.

app.cash.quiver.extensions.Ior.kt Maven / Gradle / Ivy

Go to download

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) } }
  )




© 2015 - 2024 Weber Informatics LLC | Privacy Policy