
cats.laws.TraverseLaws.scala Maven / Gradle / Ivy
The newest version!
package cats
package laws
import cats.Id
import cats.arrow.Compose
import cats.data.Const
import cats.syntax.traverse._
import cats.syntax.foldable._
trait TraverseLaws[F[_]] extends FunctorLaws[F] with FoldableLaws[F] {
implicit override def F: Traverse[F]
def traverseIdentity[A, B](fa: F[A], f: A => B): IsEq[F[B]] = {
fa.traverse[Id, B](f) <-> F.map(fa)(f)
}
def traverseSequentialComposition[A, B, C, M[_], N[_]](
fa: F[A],
f: A => M[B],
g: B => N[C]
)(implicit
N: Applicative[N],
M: Applicative[M]
): IsEq[M[N[F[C]]]] = {
implicit val MN = M.compose(N)
type MN[Z] = M[N[Z]]
val lhs: MN[F[C]] = M.map(fa.traverse(f))(fb => fb.traverse(g))
val rhs: MN[F[C]] = fa.traverse[MN, C](a => M.map(f(a))(g))
lhs <-> rhs
}
def traverseParallelComposition[A, B, M[_], N[_]](
fa: F[A],
f: A => M[B],
g: A => N[B]
)(implicit
N: Applicative[N],
M: Applicative[M]
): IsEq[(M[F[B]], N[F[B]])] = {
type MN[Z] = (M[Z], N[Z])
implicit val MN = new Applicative[MN] {
override def pure[X](x: X): MN[X] = (M.pure(x), N.pure(x))
override def ap[X, Y](fa: MN[X])(f: MN[X => Y]): MN[Y] = {
val (fam, fan) = fa
val (fm, fn) = f
(M.ap(fam)(fm), N.ap(fan)(fn))
}
}
val lhs: MN[F[B]] = fa.traverse[MN, B](a => (f(a), g(a)))
val rhs: MN[F[B]] = (fa.traverse(f), fa.traverse(g))
lhs <-> rhs
}
def foldMapDerived[A, B](
fa: F[A],
f: A => B
)(implicit B: Monoid[B]): IsEq[B] = {
val lhs: B = fa.traverse[Const[B, ?], B](a => Const(f(a))).getConst
val rhs: B = fa.foldMap(f)
lhs <-> rhs
}
}
object TraverseLaws {
def apply[F[_]](implicit ev: Traverse[F]): TraverseLaws[F] =
new TraverseLaws[F] { def F: Traverse[F] = ev }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy