or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

alternative-laws.mdbifunctor-laws.mdcategory-laws.mdcommutative-laws.mdcomonad-laws.mdcore-laws.mderror-laws.mdindex.mdparallel-laws.mdtesting-utilities.mdtraversal-laws.md
tile.json

comonad-laws.mddocs/

Comonad Laws

Laws for comonads and coflatMap operations, dual to monads with extraction instead of injection.

Imports

import cats.laws._
import cats.laws.discipline._
import cats.Comonad
import cats.CoflatMap

CoflatMap Laws

trait CoflatMapLaws[F[_]] extends FunctorLaws[F] {
  implicit override def F: CoflatMap[F]
  
  def coflatMapAssociativity[A, B, C](fa: F[A], f: F[A] => B, g: F[B] => C): IsEq[F[C]]
  def coflattenThroughMap[A](fa: F[A]): IsEq[F[F[F[A]]]]
  def coflattenCoherence[A, B](fa: F[A], f: F[A] => B): IsEq[F[B]]
  def coflatMapIdentity[A, B](fa: F[A], f: A => B): IsEq[F[B]]
  def mproductConsistency[A, B](fa: F[A], f: F[A] => B): IsEq[F[(A, B)]]
}

object CoflatMapLaws {
  def apply[F[_]](implicit ev: CoflatMap[F]): CoflatMapLaws[F]
}

CoflatMapTests

trait CoflatMapTests[F[_]] extends FunctorTests[F] {
  def laws: CoflatMapLaws[F]
  
  def coflatMap[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit
    ArbFA: Arbitrary[F[A]],
    CogenA: Cogen[A],
    CogenB: Cogen[B],
    CogenC: Cogen[C],
    CogenFA: Cogen[F[A]],
    CogenFB: Cogen[F[B]],
    EqFA: Eq[F[A]],
    EqFB: Eq[F[B]],
    EqFC: Eq[F[C]],
    EqFFFA: Eq[F[F[F[A]]]],
    EqFAB: Eq[F[(A, B)]]
  ): RuleSet
}

object CoflatMapTests {
  def apply[F[_]: CoflatMap]: CoflatMapTests[F]
}

Comonad Laws

trait ComonadLaws[F[_]] extends CoflatMapLaws[F] {
  implicit override def F: Comonad[F]
  
  def extractCoflattenIdentity[A](fa: F[A]): IsEq[F[A]]
  def mapCoflattenIdentity[A](fa: F[A]): IsEq[F[A]] 
  def comonadLeftIdentity[A](fa: F[A]): IsEq[F[A]]
  def comonadRightIdentity[A, B](fa: F[A], f: F[A] => B): IsEq[B]
}

object ComonadLaws {
  def apply[F[_]](implicit ev: Comonad[F]): ComonadLaws[F] 
}

ComonadTests

trait ComonadTests[F[_]] extends CoflatMapTests[F] {
  def laws: ComonadLaws[F]
  
  def comonad[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit
    ArbFA: Arbitrary[F[A]],
    CogenA: Cogen[A],
    CogenB: Cogen[B],
    CogenC: Cogen[C],
    CogenFA: Cogen[F[A]],
    CogenFB: Cogen[F[B]],
    EqA: Eq[A],
    EqB: Eq[B],
    EqFA: Eq[F[A]],
    EqFB: Eq[F[B]],
    EqFC: Eq[F[C]],
    EqFFFA: Eq[F[F[F[A]]]],
    EqFAB: Eq[F[(A, B)]]
  ): RuleSet
}

object ComonadTests {
  def apply[F[_]: Comonad]: ComonadTests[F]
}

Usage Examples

Testing NonEmptyList as Comonad

import cats.laws.discipline.ComonadTests
import cats.data.NonEmptyList

class NonEmptyListComonadTest extends AnyFunSuite with Checkers {
  checkAll("NonEmptyList.ComonadLaws", ComonadTests[NonEmptyList].comonad[Int, String, Double])
}