CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-typelevel--cats-laws-native0-5-2-13

Laws for testing type class instances in the Cats functional programming library for Scala

Overview
Eval results
Files

bifunctor-laws.mddocs/

Bifunctor Laws

Laws for bifunctors and related binary type constructors that can map over both type parameters.

Imports

import cats.laws._
import cats.laws.discipline._
import cats.Bifunctor
import cats.Bifoldable
import cats.Bitraverse

Bifunctor Laws

Laws for functors with two type parameters.

trait BifunctorLaws[F[_, _]] {
  implicit def F: Bifunctor[F]
  
  def bifunctorIdentity[A, B](fa: F[A, B]): IsEq[F[A, B]]
  def bifunctorComposition[A, B, C, X, Y, Z](fa: F[A, X], f: A => B, f2: B => C, g: X => Y, g2: Y => Z): IsEq[F[C, Z]]
  def bifunctorLeftMapIdentity[A, B](fa: F[A, B]): IsEq[F[A, B]]
  def bifunctorLeftMapComposition[A, B, C, D](fa: F[A, B], f: A => C, g: C => D): IsEq[F[D, B]]
}

object BifunctorLaws {
  def apply[F[_, _]](implicit ev: Bifunctor[F]): BifunctorLaws[F]
}

BifunctorTests

trait BifunctorTests[F[_, _]] {
  def laws: BifunctorLaws[F]
  
  def bifunctor[A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, G: Arbitrary](implicit
    ArbFAB: Arbitrary[F[A, B]],
    CogenA: Cogen[A],
    CogenB: Cogen[B],
    CogenC: Cogen[C],
    CogenD: Cogen[D],
    EqFAB: Eq[F[A, B]],
    EqFCD: Eq[F[C, D]],
    EqFEG: Eq[F[E, G]]
  ): RuleSet
}

object BifunctorTests {
  def apply[F[_, _]: Bifunctor]: BifunctorTests[F]
}

Bifoldable Laws

Laws for structures that can be folded over both type parameters.

trait BifoldableLaws[F[_, _]] {
  implicit def F: Bifoldable[F]
  
  def bifoldLeftConsistentWithBifoldMap[A, B, C](
    fab: F[A, B],
    f: A => C,
    g: B => C
  )(implicit C: Monoid[C]): IsEq[C]
  def bifoldRightConsistentWithBifoldMap[A, B, C](
    fab: F[A, B],
    f: A => C,
    g: B => C,
    initial: C
  )(implicit C: Monoid[C]): IsEq[C]
  def bifoldLeftConsistentWithBifoldMap[A, B, C](
    fab: F[A, B],
    f: A => C,
    g: B => C,
    initial: C
  )(implicit C: Monoid[C]): IsEq[C]
}

object BifoldableLaws {
  def apply[F[_, _]](implicit ev: Bifoldable[F]): BifoldableLaws[F]
}

BifoldableTests

trait BifoldableTests[F[_, _]] {
  def laws: BifoldableLaws[F]
  
  def bifoldable[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit
    ArbFAB: Arbitrary[F[A, B]],
    A: Monoid[A],
    B: Monoid[B],
    C: Monoid[C],
    CogenA: Cogen[A],
    CogenB: Cogen[B],
    EqA: Eq[A],
    EqB: Eq[B],
    EqC: Eq[C]
  ): RuleSet
}

object BifoldableTests {
  def apply[F[_, _]: Bifoldable]: BifoldableTests[F]
}

Bitraverse Laws

Laws for structures that can be traversed over both type parameters with applicative effects.

trait BitraverseLaws[F[_, _]] extends BifunctorLaws[F] with BifoldableLaws[F] {
  implicit override def F: Bitraverse[F]
  
  def bitraverseIdentity[A, B](fab: F[A, B]): IsEq[F[A, B]]
  def bitraverseCompose[G[_], A, B, C, D, E, H](
    fab: F[A, B],
    f: A => G[C],
    g: B => G[D],
    h: C => G[E],
    i: D => G[H]
  )(implicit G: Applicative[G]): IsEq[G[G[F[E, H]]]]
}

object BitraverseLaws {
  def apply[F[_, _]](implicit ev: Bitraverse[F]): BitraverseLaws[F]
}

BitraverseTests

trait BitraverseTests[F[_, _]] extends BifunctorTests[F] with BifoldableTests[F] {
  def laws: BitraverseLaws[F]
  
  def bitraverse[A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, G: Arbitrary, M: Applicative, N: Applicative](implicit
    ArbFAB: Arbitrary[F[A, B]],
    ArbFMAMB: Arbitrary[F[M[A], M[B]]],
    CogenA: Cogen[A],
    CogenB: Cogen[B],
    CogenC: Cogen[C],
    CogenD: Cogen[D],
    EqFAB: Eq[F[A, B]],
    EqFCD: Eq[F[C, D]],
    EqFEG: Eq[F[E, G]],
    EqMFAB: Eq[M[F[A, B]]],
    EqMFCD: Eq[M[F[C, D]]],
    EqMFEG: Eq[M[F[E, G]]],
    EqMNFEG: Eq[M[N[F[E, G]]]]
  ): RuleSet
}

object BitraverseTests {
  def apply[F[_, _]: Bitraverse]: BitraverseTests[F]
}

Usage Examples

Testing Either as Bifunctor

import cats.laws.discipline.BifunctorTests
import cats.syntax.all._

class EitherBifunctorTest extends AnyFunSuite with Checkers {
  checkAll("Either.BifunctorLaws", BifunctorTests[Either].bifunctor[Int, String, Double, Boolean, Long, Char])
}

Testing Tuple2 as Bitraverse

import cats.laws.discipline.BitraverseTests

class Tuple2BitraverseTest extends AnyFunSuite with Checkers {
  checkAll("Tuple2.BitraverseLaws", BitraverseTests[Tuple2].bitraverse[Int, String, Double, Boolean, Long, Char, Option, Option])
}

Custom Bifunctor Law Verification

import cats.laws.BifunctorLaws
import cats.syntax.all._

val laws = BifunctorLaws[Either]

// Verify bifunctor identity law
val identityLaw = laws.bifunctorIdentity(Right("hello"): Either[Int, String])
assert(identityLaw.lhs == identityLaw.rhs)

// Verify bifunctor composition law
val compositionLaw = laws.bifunctorComposition(
  Left(5): Either[Int, String],
  (x: Int) => x * 2, (x: Int) => x + 1,
  (s: String) => s.length, (i: Int) => i.toString
)
assert(compositionLaw.lhs == compositionLaw.rhs)

Install with Tessl CLI

npx tessl i tessl/maven-org-typelevel--cats-laws-native0-5-2-13

docs

alternative-laws.md

bifunctor-laws.md

category-laws.md

commutative-laws.md

comonad-laws.md

core-laws.md

error-laws.md

index.md

parallel-laws.md

testing-utilities.md

traversal-laws.md

tile.json