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

commonMain.io.kotest.property.arrow.optics.IsoLaws.kt Maven / Gradle / Ivy

@file:Suppress("MemberVisibilityCanBePrivate", "unused")

package io.kotest.property.arrow.optics

import arrow.core.compose
import arrow.core.identity
import arrow.optics.Iso
import io.kotest.property.Arb
import io.kotest.property.PropertyContext
import io.kotest.property.arrow.laws.Law
import io.kotest.property.arrow.laws.equalUnderTheLaw
import io.kotest.property.checkAll

public object IsoLaws {

  public fun  laws(
    iso: Iso,
    aGen: Arb,
    bGen: Arb,
    funcGen: Arb<(B) -> B>,
    eqa: (A, A) -> Boolean = { a, b -> a == b },
    eqb: (B, B) -> Boolean = { a, b -> a == b }
  ): List =
    listOf(
      Law("Iso Law: round trip one way") { iso.roundTripOneWay(aGen, eqa) },
      Law("Iso Law: round trip other way") { iso.roundTripOtherWay(bGen, eqb) },
      Law("Iso Law: modify identity is identity") { iso.modifyIdentity(aGen, eqa) },
      Law("Iso Law: compose modify") { iso.composeModify(aGen, funcGen, eqa) },
      Law("Iso Law: consitent set with modify") { iso.consistentSetModify(aGen, bGen, eqa) }
    )

  public suspend fun  Iso.roundTripOneWay(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext =
    checkAll(aGen) { a ->
      reverseGet(get(a)).equalUnderTheLaw(a, eq)
    }

  public suspend fun  Iso.roundTripOtherWay(bGen: Arb, eq: (B, B) -> Boolean): PropertyContext =
    checkAll(bGen) { b ->
      get(reverseGet(b)).equalUnderTheLaw(b, eq)
    }

  public suspend fun  Iso.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext =
    checkAll(aGen) { a ->
      modify(a, ::identity).equalUnderTheLaw(a, eq)
    }

  public suspend fun  Iso.composeModify(aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext =
    checkAll(aGen, funcGen, funcGen) { a, f, g ->
      modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq)
    }

  public suspend fun  Iso.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext =
    checkAll(aGen, bGen) { a, b ->
      set(b).equalUnderTheLaw(modify(a) { b }, eq)
    }
}