
scalaz.Isomorphism.scala Maven / Gradle / Ivy
package scalaz
trait IsomorphismsLow1 {
self: Isomorphisms =>
/**Set isomorphism is commutative */
implicit def isoCommutative[A, B](implicit i: A <=> B): B <=> A = i.flip
/**Natural isomorphism is commutative */
implicit def isoNaturalCommutative[F[_], G[_]](implicit i: F <~> G): G <~> F = i.flip
}
trait IsomorphismsLow0 extends IsomorphismsLow1 {
self: Isomorphisms =>
/**Set isomorphism is reflexive */
implicit def isoRefl[A]: A <=> A = new (A <=> A) {
def to: A => A = a => a
def from: A => A = a => a
}
/**Natural isomorphism is reflexive */
implicit def isoNaturalRefl[F[_]]: F <~> F = new IsoFunctorTemplate[F, F] {
def to[A](fa: F[A]): F[A] = fa
def from[A](fa: F[A]): F[A] = fa
}
}
trait Isomorphisms extends IsomorphismsLow0{
/**Isomorphism for arrows of kind * -> * -> * */
trait Iso[Arr[_, _], A, B] {
self =>
def to: Arr[A, B]
def from: Arr[B, A]
def flip = new Iso[Arr, B, A] {
val to = self.from
val from = self.to
}
}
/**Isomorphism for arrows of kind (* -> *) -> (* -> *) -> * */
trait Iso2[Arr[_[_], _[_]], F[_], G[_]] {
self =>
def to: Arr[F, G]
def from: Arr[G, F]
def flip = new Iso2[Arr, G, F] {
val to = self.from
val from = self.to
}
}
/**Isomorphism for arrows of kind (* -> * -> *) -> (* -> * -> *) -> * */
trait Iso3[Arr[_[_, _], _[_, _]], F[_, _], G[_, _]] {
self =>
def to: Arr[F, G]
def from: Arr[G, F]
def flip = new Iso3[Arr, G, F] {
val to = self.from
val from = self.to
}
}
/**Set isomorphism */
type IsoSet[A, B] = Iso[Function1, A, B]
/**Natural isomorphism between functors */
type IsoFunctor[F[_], G[_]] = Iso2[NaturalTransformation, F, G]
type IsoBifunctor[F[_, _], G[_, _]] = Iso3[~~>, F, G]
/**Alias for IsoSet */
type <=>[A, B] = IsoSet[A, B]
/**Alias for IsoFunctor */
type <~>[F[_], G[_]] = IsoFunctor[F, G]
/**Convenience template trait to implement `<~>` */
trait IsoFunctorTemplate[F[_], G[_]] extends IsoFunctor[F, G] {
final val to: NaturalTransformation[F, G] = new (F ~> G) {
def apply[A](fa: F[A]): G[A] = to[A](fa)
}
final val from: NaturalTransformation[G, F] = new (G ~> F) {
def apply[A](ga: G[A]): F[A] = from[A](ga)
}
def to[A](fa: F[A]): G[A]
def from[A](ga: G[A]): F[A]
}
/**Alias for IsoBifunctor */
type <~~>[F[_, _], G[_, _]] = IsoBifunctor[F, G]
/**Convenience template trait to implement `<~~>` */
trait IsoBifunctorTemplate[F[_, _], G[_, _]] extends IsoBifunctor[F, G] {
final val to: BiNaturalTransformation[F, G] = new (F ~~> G) {
def apply[A, B](fab: F[A, B]): G[A, B] = to[A, B](fab)
}
final val from: BiNaturalTransformation[G, F] = new (G ~~> F) {
def apply[A, B](gab: G[A, B]): F[A, B] = from[A, B](gab)
}
def to[A, B](fa: F[A, B]): G[A, B]
def from[A, B](ga: G[A, B]): F[A, B]
}
}
object Isomorphism extends Isomorphisms
//
// Derive a type class instance through an Isomorphism
//
import Isomorphism._
trait IsomorphismSemigroup[F, G] extends Semigroup[F] {
implicit def G: Semigroup[G]
def iso: F <=> G
def append(f1: F, f2: => F): F = iso.from(G.append(iso.to(f1), iso.to(f2)))
}
trait IsomorphismMonoid[F, G] extends Monoid[F] with IsomorphismSemigroup[F, G] {
implicit def G: Monoid[G]
def iso: F <=> G
def zero: F = iso.from(G.zero)
}
trait IsomorphismGroup[F, G] extends Group[F] with IsomorphismMonoid[F, G] {
implicit def G: Group[G]
def iso: F <=> G
def inverse(f: F): F = iso.from(G.inverse(iso.to(f)))
}
trait IsomorphismEqual[F, G] extends Equal[F] {
implicit def G: Equal[G]
def iso: F <=> G
def equal(a1: F, a2: F): Boolean = G.equal(iso.to(a1), iso.to(a2))
}
trait IsomorphismShow[F, G] extends Show[F] {
implicit def G: Show[G]
def iso: F <=> G
override def show(f: F): Cord = G.show(iso.to(f))
}
trait IsomorphismOrder[F, G] extends Order[F] {
implicit def G: Order[G]
def iso: F <=> G
def order(x: F, y: F): Ordering = G.order(iso.to(x), iso.to(y))
}
trait IsomorphismEach[F[_], G[_]] extends Each[F] {
implicit def G: Each[G]
def iso: F <~> G
def each[A](fa: F[A])(f: (A) => Unit) = G.each(iso.to(fa))(f)
}
trait IsomorphismIndex[F[_], G[_]] extends Index[F] {
implicit def G: Index[G]
def iso: F <~> G
def index[A](fa: F[A], n: Int): Option[A] = G.index(iso.to(fa), n)
}
trait IsomorphismFunctor[F[_], G[_]] extends Functor[F] {
implicit def G: Functor[G]
def iso: F <~> G
override def map[A, B](fa: F[A])(f: A => B): F[B] = iso.from(G.map(iso.to(fa))(f))
}
trait IsomorphismPointed[F[_], G[_]] extends Pointed[F] with IsomorphismFunctor[F, G] {
implicit def G: Pointed[G]
def point[A](a: => A): F[A] = iso.from(G.point(a))
}
trait IsomorphismContravariant[F[_], G[_]] extends Contravariant[F] {
implicit def G: Contravariant[G]
def iso: F <~> G
def contramap[A, B](r: F[A])(f: B => A): F[B] = iso.from(G.contramap(iso.to(r))(f))
}
trait IsomorphismCopointed[F[_], G[_]] extends Copointed[F] {
implicit def G: Copointed[G]
def iso: F <~> G
def copoint[A](p: F[A]): A = G.copoint(iso.to(p))
}
trait IsomorphismApply[F[_], G[_]] extends Apply[F] with IsomorphismFunctor[F, G] {
implicit def G: Apply[G]
override def ap[A, B](fa: => F[A])(f: => F[(A) => B]): F[B] = iso.from(G.ap(iso.to(fa))(iso.to(f)))
}
trait IsomorphismApplicative[F[_], G[_]] extends Applicative[F] with IsomorphismApply[F, G] with IsomorphismPointed[F, G] {
implicit def G: Applicative[G]
override def ap[A, B](fa: => F[A])(f: => F[(A) => B]): F[B] = iso.from(G.ap(iso.to(fa))(iso.to(f)))
}
trait IsomorphismBind[F[_], G[_]] extends Bind[F] with IsomorphismApply[F, G] {
implicit def G: Bind[G]
def bind[A, B](fa: F[A])(f: A => F[B]): F[B] = iso.from(G.bind(iso.to(fa))(f.andThen(iso.to.apply)))
}
trait IsomorphismMonad[F[_], G[_]] extends Monad[F] with IsomorphismApplicative[F, G] with IsomorphismBind[F, G] {
implicit def G: Monad[G]
}
trait IsomorphismCojoin[F[_], G[_]] extends Cojoin[F] {
implicit def G: Cojoin[G] with Functor[G]
def iso: F <~> G
def cojoin[A](a: F[A]): F[F[A]] = iso.from(G.map(G.cojoin(iso.to(a)))(iso.from.apply))
}
trait IsomorphismComonad[F[_], G[_]] extends Comonad[F] with IsomorphismCojoin[F, G] with IsomorphismCopointed[F, G] {
implicit def G: Comonad[G] with Functor[G] with Copointed[G]
}
trait IsomorphismPlus[F[_], G[_]] extends Plus[F] {
implicit def G: Plus[G]
def iso: F <~> G
def plus[A](a: F[A], b: => F[A]): F[A] = iso.from(G.plus(iso.to(a), iso.to(b)))
}
trait IsomorphismEmpty[F[_], G[_]] extends PlusEmpty[F] with IsomorphismPlus[F, G] {
implicit def G: PlusEmpty[G]
def empty[A]: F[A] = iso.from(G.empty[A])
}
trait IsomorphismApplicativePlus[F[_], G[_]] extends ApplicativePlus[F] with IsomorphismEmpty[F, G] with IsomorphismApplicative[F, G] {
implicit def G: ApplicativePlus[G]
}
trait IsomorphismMonadPlus[F[_], G[_]] extends MonadPlus[F] with IsomorphismEmpty[F, G] with IsomorphismMonad[F, G] {
implicit def G: MonadPlus[G]
}
trait IsomorphismFoldable[F[_], G[_]] extends Foldable[F] {
implicit def G: Foldable[G]
def iso: F <~> G
override def foldMap[A, B](fa: F[A])(f: (A) => B)(implicit F: Monoid[B]) = G.foldMap(iso.to(fa))(f)
override def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B) = G.foldLeft(iso.to(fa), z)(f)
override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B): B = G.foldRight[A, B](iso.to(fa), z)(f)
}
trait IsomorphismTraverse[F[_], G[_]] extends Traverse[F] with IsomorphismFoldable[F, G] with IsomorphismFunctor[F, G] {
implicit def G: Traverse[G]
def traverseImpl[H[_] : Applicative, A, B](fa: F[A])(f: (A) => H[B]): H[F[B]] =
Applicative[H].map(G.traverseImpl(iso.to(fa))(f))(iso.from.apply)
}
trait IsomorphismBifunctor[F[_, _], G[_, _]] extends Bifunctor[F] {
def iso: F <~~> G
implicit def G: Bifunctor[G]
override def bimap[A, B, C, D](fab: F[A, B])(f: (A) => C, g: (B) => D): F[C, D] =
iso.from(G.bimap(iso.to(fab))(f, g))
}
trait IsomorphismBitraverse[F[_, _], G[_, _]] extends Bitraverse[F] with IsomorphismBifunctor[F, G] {
implicit def G: Bitraverse[G]
def bitraverseImpl[H[_]: Applicative, A, B, C, D](fab: F[A, B])(f: (A) => H[C], g: (B) => H[D]): H[F[C, D]] =
Applicative[H].map(G.bitraverseImpl(iso.to(fab))(f, g))(iso.from.apply)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy