scalaz.Contravariant.scala Maven / Gradle / Ivy
The newest version!
package scalaz
////
import scalaz.Liskov.<~<
/**
* Contravariant functors. For example, functions provide a
* [[scalaz.Functor]] in their result type, but a
* [[scalaz.Contravariant]] for each argument type.
*
* Note that the dual of a [[scalaz.Functor]] is just a [[scalaz.Functor]]
* itself.
*
* Providing an instance of this is a useful alternative to marking a
* type parameter with `-` in Scala.
*
* @see [[scalaz.Contravariant.ContravariantLaw]]
*/
////
trait Contravariant[F[_]] extends InvariantFunctor[F] { self =>
////
/** Transform `A`.
*
* @note `contramap(r)(identity)` = `r`
*/
def contramap[A, B](r: F[A])(f: B => A): F[B]
// derived functions
def narrow[A, B](fa: F[A])(implicit ev: B <~< A): F[B] =
contramap(fa)(ev.apply)
def xmap[A, B](fa: F[A], f: A => B, g: B => A): F[B] =
contramap(fa)(g)
/** The composition of Contravariant F and G, `[x]F[G[x]]`, is
* covariant.
*/
def compose[G[_]](implicit G0: Contravariant[G]): Functor[λ[α => F[G[α]]]] =
new Functor[λ[α => F[G[α]]]] {
def map[A, B](fa: F[G[A]])(f: A => B) =
self.contramap(fa)(gb => G0.contramap(gb)(f))
}
/** The composition of Contravariant F and Functor G, `[x]F[G[x]]`,
* is contravariant.
*/
def icompose[G[_]](implicit G0: Functor[G]): Contravariant[λ[α => F[G[α]]]] =
new Contravariant[λ[α => F[G[α]]]] {
def contramap[A, B](fa: F[G[A]])(f: B => A) =
self.contramap(fa)(G0.lift(f))
}
/** The product of Contravariant `F` and `G`, `[x](F[x], G[x]])`, is
* contravariant.
*/
def product[G[_]](implicit G0: Contravariant[G]): Contravariant[λ[α => (F[α], G[α])]] =
new Contravariant[λ[α => (F[α], G[α])]] {
def contramap[A, B](fa: (F[A], G[A]))(f: B => A) =
(self.contramap(fa._1)(f), G0.contramap(fa._2)(f))
}
trait ContravariantLaw extends InvariantFunctorLaw {
/** The identity function, lifted, is a no-op. */
def identity[A](fa: F[A])(implicit FA: Equal[F[A]]): Boolean = FA.equal(contramap(fa)(x => x), fa)
/**
* A series of contramaps may be freely rewritten as a single
* contramap on a composed function.
*/
def composite[A, B, C](fa: F[A], f1: B => A, f2: C => B)(implicit FC: Equal[F[C]]): Boolean = FC.equal(contramap(contramap(fa)(f1))(f2), contramap(fa)(f1 compose f2))
}
def contravariantLaw: ContravariantLaw = new ContravariantLaw {}
////
val contravariantSyntax: scalaz.syntax.ContravariantSyntax[F] =
new scalaz.syntax.ContravariantSyntax[F] { def F = Contravariant.this }
}
object Contravariant {
@inline def apply[F[_]](implicit F: Contravariant[F]): Contravariant[F] = F
import Isomorphism._
def fromIso[F[_], G[_]](D: F <~> G)(implicit E: Contravariant[G]): Contravariant[F] =
new IsomorphismContravariant[F, G] {
override def G: Contravariant[G] = E
override def iso: F <~> G = D
}
////
////
}
trait IsomorphismContravariant[F[_], G[_]] extends Contravariant[F] with IsomorphismInvariantFunctor[F, G]{
implicit def G: Contravariant[G]
////
import Isomorphism._
def iso: F <~> G
override def contramap[A, B](r: F[A])(f: B => A): F[B] =
iso.from(G.contramap(iso.to(r))(f))
////
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy