scalaz.Arrow.scala Maven / Gradle / Ivy
The newest version!
package scalaz
////
/**
* A [[scalaz.Category]] supporting all ordinary functions, as well as
* combining arrows product-wise. Every Arrow forms a
* [[scalaz.Contravariant]] in one type parameter, and a
* [[scalaz.Applicative]] in the other, just as with ordinary
* functions.
*/
////
trait Arrow[=>:[_, _]] extends Split[=>:] with Strong[=>:] with Category[=>:] { self =>
////
/** Lift an ordinary function. */
def arr[A, B](f: A => B): A =>: B
override def covariantInstance[C]: Applicative[=>:[C, *]] =
new Applicative[=>:[C, *]] with SndCovariant[C] {
def point[A](a: => A): C =>: A = arr(_ => a)
def ap[A, B](fa: => (C =>: A))(f: => (C =>: (A => B))): (C =>: B) = <<<(arr((y: (A => B, A)) => y._1(y._2)), combine(f, fa))
}
/** Alias for `compose`. */
final def <<<[A, B, C](fbc: (B =>: C), fab: (A =>: B)): =>:[A, C] =
compose(fbc, fab)
/** Flipped `<<<`. */
def >>>[A, B, C](fab: (A =>: B), fbc: (B =>: C)): (A =>: C) =
compose(fbc, fab)
/** Swaps a pair. */
def swap[X, Y]: ((X, Y) =>: (Y, X)) = arr[(X, Y), (Y, X)] {
case (x, y) => (y, x)
}
/** Pass `C` through untouched. */
override def second[A, B, C](f: (A =>: B)): ((C, A) =>: (C, B)) = {
>>>(<<<(first[A, B, C](f), swap), swap)
}
/** Alias for `split`. */
final def splitA[A, B, C, D](fab: (A =>: B), fcd: (C =>: D)): ((A, C) =>: (B, D)) =
split(fab, fcd)
/** Run `fab` and `fcd` alongside each other. Sometimes `***`. */
def split[A, B, C, D](f: A =>: B, g: C =>: D): ((A, C) =>: (B, D)) =
>>>(first[A, B, C](f), second[C, D, B](g))
/** Run two `fab`s alongside each other. */
def product[A, B](fab: (A =>: B)): ((A, A) =>: (B, B)) =
splitA(fab, fab)
/** Run `fab` and `fac` on the same `A`. Sometimes `&&&`. */
def combine[A, B, C](fab: (A =>: B), fac: (A =>: C)): (A =>: (B, C)) =
>>>(arr((a: A) => (a, a)), splitA(fab, fac))
/** Contramap on `A`. */
def mapfst[A, B, C](fab: (A =>: B))(f: C => A): (C =>: B) =
>>>[C, A, B](arr(f), fab)
/** Functor map on `B`. */
def mapsnd[A, B, C](fab: (A =>: B))(f: B => C): (A =>: C) =
<<<[A, B, C](arr(f), fab)
////
val arrowSyntax: scalaz.syntax.ArrowSyntax[=>:] =
new scalaz.syntax.ArrowSyntax[=>:] { def F = Arrow.this }
}
object Arrow {
@inline def apply[F[_, _]](implicit F: Arrow[F]): Arrow[F] = F
import Isomorphism._
def fromIso[F[_, _], G[_, _]](D: F <~~> G)(implicit E: Arrow[G]): Arrow[F] =
new IsomorphismArrow[F, G] {
override def G: Arrow[G] = E
override def iso: F <~~> G = D
}
////
////
}
trait IsomorphismArrow[F[_, _], G[_, _]] extends Arrow[F] with IsomorphismSplit[F, G] with IsomorphismStrong[F, G] with IsomorphismCategory[F, G]{
implicit def G: Arrow[G]
////
override def arr[A, B](f: A => B): F[A, B] =
iso.from(G.arr(f))
////
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy