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

commonMain.arrow.optics.Traversal.kt Maven / Gradle / Ivy

There is a newer version: 2.0.1-alpha.1
Show newest version
package arrow.optics

import arrow.core.Either
import arrow.core.NonEmptyList
import arrow.core.Option
import arrow.core.Tuple10
import arrow.core.Tuple4
import arrow.core.Tuple5
import arrow.core.Tuple6
import arrow.core.Tuple7
import arrow.core.Tuple8
import arrow.core.Tuple9
import kotlin.jvm.JvmStatic

/**
 * [Traversal] is a type alias for [PTraversal] which fixes the type arguments
 * and restricts the [PTraversal] to monomorphic updates.
 */
public typealias Traversal = PTraversal

/**
 * A [Traversal] is an optic that allows to see into a structure with 0 to N foci.
 *
 * [Traversal] is a generalisation of [kotlin.collections.map] and can be seen as a representation of modify.
 * all methods are written in terms of modify
 *
 * @param S the source of a [PTraversal]
 * @param T the modified source of a [PTraversal]
 * @param A the target of a [PTraversal]
 * @param B the modified target of a [PTraversal]
 */
public fun interface PTraversal : PSetter {

  override fun modify(source: S, map: (focus: A) -> B): T

  public fun  choice(other: PTraversal): PTraversal, Either, A, B> =
    PTraversal { s, f ->
      s.fold(
        { a -> Either.Left(this.modify(a, f)) },
        { u -> Either.Right(other.modify(u, f)) }
      )
    }

  /**
   * Compose a [PTraversal] with a [PTraversal]
   */
  public infix fun  compose(other: PTraversal): PTraversal =
    PTraversal { s, f -> this.modify(s) { b -> other.modify(b, f) } }

  public operator fun  plus(other: PTraversal): PTraversal =
    this compose other

  public companion object {
    public fun  id(): PTraversal =
      PIso.id()

    public fun  codiagonal(): Traversal, S> =
      Traversal { s, f -> s.mapLeft(f).map(f) }

    /**
     * [PTraversal] that points to nothing
     */
    public fun  void(): Traversal =
      POptional.void()

    /**
     * [PTraversal] constructor from multiple getters of the same source.
     */
    public operator fun  invoke(get1: (S) -> A, get2: (S) -> A, set: (B, B, S) -> T): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      set: (B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      set: (B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      set: (B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      get6: (S) -> A,
      set: (B, B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), f(get6(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      get6: (S) -> A,
      get7: (S) -> A,
      set: (B, B, B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), f(get6(s)), f(get7(s)), s) }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      get6: (S) -> A,
      get7: (S) -> A,
      get8: (S) -> A,
      set: (B, B, B, B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f ->
        set(
          f(get1(s)),
          f(get2(s)),
          f(get3(s)),
          f(get4(s)),
          f(get5(s)),
          f(get6(s)),
          f(get7(s)),
          f(get8(s)),
          s
        )
      }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      get6: (S) -> A,
      get7: (S) -> A,
      get8: (S) -> A,
      get9: (S) -> A,
      set: (B, B, B, B, B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f ->
        set(
          f(get1(s)),
          f(get2(s)),
          f(get3(s)),
          f(get4(s)),
          f(get5(s)),
          f(get6(s)),
          f(get7(s)),
          f(get8(s)),
          f(get9(s)),
          s
        )
      }

    public operator fun  invoke(
      get1: (S) -> A,
      get2: (S) -> A,
      get3: (S) -> A,
      get4: (S) -> A,
      get5: (S) -> A,
      get6: (S) -> A,
      get7: (S) -> A,
      get8: (S) -> A,
      get9: (S) -> A,
      get10: (S) -> A,
      set: (B, B, B, B, B, B, B, B, B, B, S) -> T
    ): PTraversal =
      PTraversal { s, f ->
        set(
          f(get1(s)),
          f(get2(s)),
          f(get3(s)),
          f(get4(s)),
          f(get5(s)),
          f(get6(s)),
          f(get7(s)),
          f(get8(s)),
          f(get9(s)),
          f(get10(s)),
          s
        )
      }

    /**
     * [Traversal] for [List] that focuses in each [A] of the source [List].
     */
    @JvmStatic
    public fun  list(): Traversal, A> =
      Every.list()

    /**
     * [Traversal] for [Either] that has focus in each [Either.Right].
     *
     * @return [Traversal] with source [Either] and focus every [Either.Right] of the source.
     */
    @JvmStatic
    public fun  either(): Traversal, R> =
      Every.either()

    @JvmStatic
    public fun  map(): Traversal, V> =
      Every.map()

    /**
     * [Traversal] for [NonEmptyList] that has focus in each [A].
     *
     * @receiver [PTraversal.Companion] to make it statically available.
     * @return [Traversal] with source [NonEmptyList] and focus every [A] of the source.
     */
    @JvmStatic
    public fun  nonEmptyList(): Traversal, A> =
      Every.nonEmptyList()

    /**
     * [Traversal] for [Option] that has focus in each [arrow.core.Some].
     *
     * @receiver [PTraversal.Companion] to make it statically available.
     * @return [Traversal] with source [Option] and focus in every [arrow.core.Some] of the source.
     */
    @JvmStatic
    public fun  option(): Traversal, A> =
      Every.option()

    @JvmStatic
    public fun  sequence(): Traversal, A> =
      Every.sequence()

    /**
     * [Traversal] for [String] that focuses in each [Char] of the source [String].
     *
     * @receiver [PTraversal.Companion] to make it statically available.
     * @return [Traversal] with source [String] and foci every [Char] in the source.
     */
    @JvmStatic
    public fun string(): Traversal =
      Every.string()

    /**
     * [PTraversal] to focus into the first and second value of a [Pair]
     */
    @JvmStatic
    public fun  pPair(): PTraversal, Pair, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        set = { a, b, _ -> a to b }
      )

    /**
     * [Traversal] to focus into the first and second value of a [Pair]
     */
    @JvmStatic
    public fun  pair(): Traversal, A> =
      pPair()

    /**
     * [PTraversal] to focus into the first, second and third value of a [Triple]
     */
    @JvmStatic
    public fun  pTriple(): PTraversal, Triple, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        set = { a, b, c, _ -> Triple(a, b, c) }
      )

    /**
     * [Traversal] to focus into the first, second and third value of a [Triple]
     */
    @JvmStatic
    public fun  triple(): Traversal, A> =
      pTriple()

    /**
     * [PTraversal] to focus into the first, second, third and fourth value of a [arrow.core.Tuple4]
     */
    @JvmStatic
    public fun  pTuple4(): PTraversal, Tuple4, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        set = { a, b, c, d, _ -> Tuple4(a, b, c, d) }
      )

    /**
     * [Traversal] to focus into the first, second, third and fourth value of a [arrow.core.Tuple4]
     */
    @JvmStatic
    public fun  tuple4(): Traversal, A> =
      pTuple4()

    /**
     * [PTraversal] to focus into the first, second, third, fourth and fifth value of a [arrow.core.Tuple5]
     */
    @JvmStatic
    public fun  pTuple5(): PTraversal, Tuple5, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        set = { a, b, c, d, e, _ -> Tuple5(a, b, c, d, e) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth and fifth value of a [arrow.core.Tuple5]
     */
    @JvmStatic
    public fun  tuple5(): Traversal, A> =
      pTuple5()

    /**
     * [PTraversal] to focus into the first, second, third, fourth, fifth and sixth value of a [arrow.core.Tuple6]
     */
    @JvmStatic
    public fun  pTuple6(): PTraversal, Tuple6, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        get6 = { it.sixth },
        set = { a, b, c, d, e, f, _ -> Tuple6(a, b, c, d, e, f) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth, fifth and sixth value of a [arrow.core.Tuple6]
     */
    @JvmStatic
    public fun  tuple6(): Traversal, A> =
      pTuple6()

    /**
     * [PTraversal] to focus into the first, second, third, fourth, fifth, sixth and seventh value of a [arrow.core.Tuple7]
     */
    @JvmStatic
    public fun  pTuple7(): PTraversal, Tuple7, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        get6 = { it.sixth },
        get7 = { it.seventh },
        set = { a, b, c, d, e, f, g, _ -> Tuple7(a, b, c, d, e, f, g) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth, fifth, sixth and seventh value of a [arrow.core.Tuple7]
     */
    @JvmStatic
    public fun  tuple7(): Traversal, A> =
      pTuple7()

    /**
     * [PTraversal] to focus into the first, second, third, fourth, fifth, sixth, seventh and eight value of a [arrow.core.Tuple8]
     */
    @JvmStatic
    public fun  pTuple8(): PTraversal, Tuple8, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        get6 = { it.sixth },
        get7 = { it.seventh },
        get8 = { it.eighth },
        set = { a, b, c, d, e, f, g, h, _ -> Tuple8(a, b, c, d, e, f, g, h) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh and eight value of a [arrow.core.Tuple8]
     */
    @JvmStatic
    public fun  tuple8(): Traversal, A> =
      pTuple8()

    /**
     * [PTraversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight and ninth value of a [arrow.core.Tuple9]
     */
    @JvmStatic
    public fun  pTuple9(): PTraversal, Tuple9, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        get6 = { it.sixth },
        get7 = { it.seventh },
        get8 = { it.eighth },
        get9 = { it.ninth },
        set = { a, b, c, d, e, f, g, h, i, _ -> Tuple9(a, b, c, d, e, f, g, h, i) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight and ninth value of a [arrow.core.Tuple9]
     */
    @JvmStatic
    public fun  tuple9(): Traversal, A> =
      pTuple9()

    /**
     * [PTraversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10]
     */
    @JvmStatic
    public fun  pTuple10(): PTraversal, Tuple10, A, B> =
      PTraversal(
        get1 = { it.first },
        get2 = { it.second },
        get3 = { it.third },
        get4 = { it.fourth },
        get5 = { it.fifth },
        get6 = { it.sixth },
        get7 = { it.seventh },
        get8 = { it.eighth },
        get9 = { it.ninth },
        get10 = { it.tenth },
        set = { a, b, c, d, e, f, g, h, i, j, _ -> Tuple10(a, b, c, d, e, f, g, h, i, j) }
      )

    /**
     * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10]
     */
    @JvmStatic
    public fun  tuple10(): Traversal, A> =
      pTuple10()
  }
}