scalaz.Cofree.scala Maven / Gradle / Ivy
The newest version!
package scalaz
import Cofree.CofreeZip
/** A cofree comonad for some functor `S`, i.e. an `S`-branching stream. */
sealed abstract class Cofree[S[_], A] {
def head: A
def t: Free.Trampoline[S[Cofree[S,A]]]
/** Applies `f` to the head and `g` through the tail. */
def applyCofree[B](f: A => B, g: Cofree[S, A] => Cofree[S, B])(implicit S: Functor[S]): Cofree[S, B]
/* Derived methods */
def tail: S[Cofree[S, A]] = t.run
/** Alias for `head`, for compatibility with Scalaz 6 */
final def extract: A = head
/** Alias for `head`, for compatibility with Scalaz 6 */
final def copure: A = head
/** Alias for `tail`, for compatibility with Scalaz 6 */
final def out: S[Cofree[S, A]] = tail
final def map[B](f: A => B)(implicit S: Functor[S]): Cofree[S, B] =
applyCofree(f, _ map f)
/** Alias for `extend` */
final def `=>>`[B](f: Cofree[S, A] => B)(implicit S: Functor[S]): Cofree[S, B] = this extend f
/** Redecorates this structure with a computation whose context is the entire structure under that value. */
final def extend[B](f: Cofree[S, A] => B)(implicit S: Functor[S]): Cofree[S, B] =
applyTail(f(this), _ extend f)
/** Folds over this cofree structure, returning all the intermediate values in a new structure. */
def scanr[B](g: (A, S[Cofree[S, B]]) => B)(implicit S: Functor[S]): Cofree[S, B] = {
val qs = S.map(tail)(_ scanr g)
Cofree(g(head, qs), qs)
}
/** Redecorates the structure with values representing entire substructures. */
final def duplicate(implicit S: Functor[S]): Cofree[S, Cofree[S, A]] =
applyTail(this, _.duplicate)
/** Returns the components of this structure in a tuple. */
final def toPair: (A, S[Cofree[S, A]]) = (head, tail)
/** Changes the branching functor with the given natural transformation, using the source branching functor's fmap. */
final def mapBranching[T[_]](f: S ~> T)(implicit S: Functor[S]): Cofree[T, A] =
Cofree.delay(head, f(S.map(tail)(_ mapBranching f)))
/** Changes the branching functor with the given natural transformation, using the target branching functor's fmap. */
final def mapBranchingT[T[_]](f: S ~> T)(implicit T: Functor[T]): Cofree[T, A] =
Cofree.delay(head, T.map(f(tail))(_ mapBranchingT f))
/** Modifies the first branching with the given natural transformation. */
final def mapFirstBranching(f: S ~> S): Cofree[S, A] =
Cofree.delay(head, f(tail))
/** Injects a constant value into this structure. */
final def inject[B](b: B)(implicit S: Functor[S]): Cofree[S, B] =
applyTail(b, _ inject b)
/** Replaces the head with `b` and applies `g` through the tail. */
final def applyTail[B](b: B, g: Cofree[S, A] => Cofree[S, B])(implicit S: Functor[S]): Cofree[S, B] =
applyCofree(x => b, g)
/** Applies a function `f` to a value in this comonad and a corresponding value in the dual monad, annihilating both. */
final def zapWith[G[_], B, C](bs: Free[G, B])(f: (A, B) => C)(implicit d: Zap[S, G]): C =
Zap.comonadMonadZap.zapWith(this, bs)(f)
/** Applies a function in a monad to the corresponding value in this comonad, annihilating both. */
final def zap[G[_], B](fs: Free[G, A => B])(implicit d: Zap[S, G]): B =
zapWith(fs)((a, f) => f(a))
}
object Cofree extends CofreeInstances {
def apply[S[_], A](h: A, t: S[Cofree[S, A]]): Cofree[S,A] = applyT(h, Trampoline.done(t))
def delay[S[_], A](h: A, t: => S[Cofree[S, A]]): Cofree[S,A] = applyT(h, Trampoline.delay(t))
def unapply[S[_], A](c: Cofree[S, A]): Some[(A, S[Cofree[S,A]])] = Some( (c.head, c.tail) )
//creates an instance of Cofree that trampolines all of the calls to the tail so we get stack safety
def applyT[S[_],A](a: A, tf: Free.Trampoline[S[Cofree[S,A]]])(implicit T: Functor[Free.Trampoline]): Cofree[S, A] =
new Cofree[S,A] {
def head = a
def t = tf
def applyCofree[B](f: A => B, g: Cofree[S, A] => Cofree[S, B])(implicit S: Functor[S]): Cofree[S,B] =
applyT(f(head), T.map(t)(S.lift(g)))
}
private[scalaz] final type CofreeZip[F[_], A] = Cofree[F, A] @@ Tags.Zip
private[scalaz] final def CofreeZip[F[_], A](head: A, tail: F[Cofree[F, A]]): CofreeZip[F, A] =
Tags.Zip(Cofree(head, tail))
/** Cofree corecursion. */
def unfoldC[F[_], A](a: A)(f: A => F[A])(implicit F: Functor[F]): Cofree[F, A] =
Cofree.delay(a, F.map(f(a))(unfoldC(_)(f)))
def unfold[F[_], A, B](b: B)(f: B => (A, F[B]))(implicit F: Functor[F], T: Functor[Free.Trampoline]): Cofree[F, A] = {
val (a, fb) = f(b)
val nt = T.map(Trampoline.done(fb))(F.lift(unfold(_)(f)))
Cofree.applyT(a, nt)
}
def mapUnfold[F[_],W[_],A](z: W[A])(f: W ~> F)(implicit W: Comonad[W]): Cofree[F,A] =
Cofree.delay(W copoint z, f(W.extend(z)(mapUnfold(_:W[A])(f))))
}
sealed abstract class CofreeInstances6 {
implicit def cofreeEqual[F[_], A](implicit A0: Equal[A], F0: => Equal[F[Cofree[F, A]]]): Equal[Cofree[F, A]] =
new CofreeEqual[F, A] {
override def A = A0
override lazy val F = F0
}
implicit def cofreeZipEqual[F[_], A](implicit A: Equal[A], F: => Equal[F[CofreeZip[F, A]]]): Equal[CofreeZip[F, A]] =
Tags.Zip.subst(
cofreeEqual[F, A](A, F.contramap(Tags.Zip.subst))
)
}
sealed abstract class CofreeInstances5 extends CofreeInstances6 {
implicit def cofreeOrder[F[_], A](implicit A0: Order[A], F0: => Order[F[Cofree[F, A]]]): Order[Cofree[F, A]] =
new Order[Cofree[F, A]] with CofreeEqual[F, A] {
override lazy val F: Order[F[Cofree[F, A]]] = F0
override def A: Order[A] = A0
override def order(x: Cofree[F, A], y: Cofree[F, A]) = {
Monoid[Ordering].append(A.order(x.head, y.head), F0.order(x.tail, y.tail))
}
}
implicit def cofreeZipOrder[F[_], A](implicit A: Order[A], F: => Order[F[CofreeZip[F, A]]]): Order[CofreeZip[F, A]] =
Tags.Zip.subst(
cofreeOrder[F, A](A, F.contramap(Tags.Zip.subst))
)
}
sealed abstract class CofreeInstances4 extends CofreeInstances5 {
/** low priority `Foldable1` instance */
implicit def cofreeFoldable[F[_]: Foldable]: Foldable1[Cofree[F, *]] =
new CofreeFoldable[F]{
def F = implicitly
}
}
sealed abstract class CofreeInstances3 extends CofreeInstances4 {
/** low priority `Traverse1` instance */
implicit def cofreeTraverse[F[_]: Traverse]: Traverse1[Cofree[F, *]] =
new CofreeTraverse[F]{
def F = implicitly
}
implicit def cofreeZipFunctor[F[_]: Functor]: Functor[CofreeZip[F, *]] =
new CofreeZipFunctor[F]{
def F = implicitly
}
}
sealed abstract class CofreeInstances2 extends CofreeInstances3 {
/** high priority `Foldable1` instance. more efficient */
implicit def cofreeFoldable1[F[_]: Foldable1]: Foldable1[Cofree[F, *]] =
new CofreeFoldable1[F]{
def F = implicitly
}
implicit def cofreeBind[F[_]: Plus: Functor]: Bind[Cofree[F, *]] =
new CofreeBind[F]{
def F = implicitly
def G = implicitly
}
}
sealed abstract class CofreeInstances1 extends CofreeInstances2 {
/** high priority `Traverse1` instance. more efficient */
implicit def cofreeTraverse1[F[_]: Traverse1]: Traverse1[Cofree[F, *]] =
new CofreeTraverse1[F] {
def F = implicitly
}
implicit def cofreeZipApply[F[_]: Apply]: Apply[CofreeZip[F, *]] =
new CofreeZipApply[F]{
def F = implicitly
}
}
sealed abstract class CofreeInstances0 extends CofreeInstances1 {
implicit def cofreeZipApplicative[F[_]: Applicative]: Applicative[CofreeZip[F, *]] =
new CofreeZipApplicative[F]{
def F = implicitly
}
implicit def cofreeMonad[F[_]: PlusEmpty: Functor]: Monad[Cofree[F, *]] =
new CofreeMonad[F]{
def F = implicitly
def G = implicitly
}
}
sealed abstract class CofreeInstances extends CofreeInstances0 {
implicit def cofreeComonad[S[_]: Functor]: Comonad[Cofree[S, *]] = new CofreeComonad[S] {
def F = implicitly
}
}
private trait CofreeComonad[S[_]] extends Comonad[Cofree[S, *]] {
implicit def F: Functor[S]
def copoint[A](p: Cofree[S, A]) = p.head
override def cojoin[A](a: Cofree[S, A]) = a.duplicate
override final def map[A, B](fa: Cofree[S, A])(f: A => B) = fa map f
def cobind[A, B](fa: Cofree[S, A])(f: (Cofree[S, A]) => B) = fa extend f
}
private trait CofreeZipFunctor[F[_]] extends Functor[CofreeZip[F, *]]{
implicit def F: Functor[F]
override final def map[A, B](fa: CofreeZip[F, A])(f: A => B) = Tags.Zip(Tag unwrap fa map f)
}
private trait CofreeZipApply[F[_]] extends Apply[CofreeZip[F, *]] with CofreeZipFunctor[F]{
implicit def F: Apply[F]
override final def ap[A, B](fa: => CofreeZip[F, A])(f: => CofreeZip[F, A => B]): CofreeZip[F, B] =
Tags.Zip(
Cofree.applyT(Tag.unwrap(f).head(Tag.unwrap(fa).head),
Tag.unwrap(fa).t.flatMap(fat => Tag.unwrap(f).t.map(fab => F.apply2(Tags.Zip.subst(fat), Tags.Zip.subst(fab)) { (a, b) =>
Tag.unwrap(ap(a)(b))
}))
)
)
}
private trait CofreeZipApplicative[F[_]] extends Applicative[CofreeZip[F, *]] with CofreeZipApply[F]{
implicit def F: Applicative[F]
def point[A](a: => A) = Tags.Zip(Cofree.delay(a, F.point(Tag.unwrap[Cofree[F, A], Tags.Zip](point(a)))))
}
private trait CofreeBind[F[_]] extends Bind[Cofree[F, *]] with CofreeComonad[F]{
implicit def F: Functor[F]
implicit def G: Plus[F]
def bind[A, B](fa: Cofree[F, A])(f: A => Cofree[F, B]): Cofree[F, B] = {
val c = f(fa.head)
Cofree.applyT(c.head, c.t.map(ct => G.plus(ct, F.map(fa.tail)(bind(_)(f))) ) )
}
}
private trait CofreeMonad[F[_]] extends Monad[Cofree[F, *]] with CofreeBind[F]{
implicit def G: PlusEmpty[F]
def point[A](a: => A): Cofree[F, A] = Cofree(a, G.empty)
}
private trait CofreeFoldable[F[_]] extends Foldable1[Cofree[F, *]]{
implicit def F: Foldable[F]
override final def foldMap[A, B](fa: Cofree[F, A])(f: A => B)(implicit M: Monoid[B]): B =
M.append(f(fa.head), F.foldMap(fa.tail)(foldMap(_)(f)))
override final def foldRight[A, B](fa: Cofree[F, A], z: => B)(f: (A, => B) => B): B =
f(fa.head, F.foldRight(fa.tail, z)(foldRight(_, _)(f)))
override final def foldLeft[A, B](fa: Cofree[F, A], z: B)(f: (B, A) => B): B =
F.foldLeft(fa.tail, f(z, fa.head))((b, c) => foldLeft(c, b)(f))
override final def foldMapLeft1[A, B](fa: Cofree[F, A])(z: A => B)(f: (B, A) => B): B =
F.foldLeft(fa.tail, z(fa.head))((b, c) => foldLeft(c, b)(f))
override def foldMapRight1[A, B](fa: Cofree[F, A])(z: A => B)(f: (A, => B) => B): B = {
import std.option.none
foldRight(fa, none[B]){
case (l, None) => Some(z(l))
case (l, Some(r)) => Some(f(l, r))
}.getOrElse(sys.error("foldMapRight1"))
}
override def foldMap1[A, B](fa: Cofree[F, A])(f: A => B)(implicit S: Semigroup[B]): B = {
val h = f(fa.head)
F.foldMap1Opt(fa.tail)(foldMap1(_)(f)).map(S.append(h, _)).getOrElse(h)
}
}
private trait CofreeFoldable1[F[_]] extends Foldable1[Cofree[F, *]] with CofreeFoldable[F]{
implicit def F: Foldable1[F]
override final def foldMap1[A, B](fa: Cofree[F, A])(f: A => B)(implicit S: Semigroup[B]): B =
S.append(f(fa.head), F.foldMap1(fa.tail)(foldMap1(_)(f)))
}
private trait CofreeTraverse[F[_]] extends Traverse1[Cofree[F, *]] with CofreeFoldable[F] with CofreeComonad[F]{
implicit def F: Traverse[F]
override final def traverseImpl[G[_], A, B](fa: Cofree[F,A])(f: A => G[B])(implicit G: Applicative[G]): G[Cofree[F,B]] =
G.apply2(f(fa.head), F.traverse(fa.tail)(traverse(_)(f)))(Cofree(_, _))
override def traverse1Impl[G[_], A, B](fa: Cofree[F,A])(f: A => G[B])(implicit G: Apply[G]): G[Cofree[F,B]] =
G.applyApplicative.traverse[Cofree[F, A], F, Cofree[F, B]](fa.tail)(a => -\/(traverse1(a)(f)))
.fold(ftl => G.apply2(f(fa.head), ftl)(Cofree(_, _)),
tl => G.map(f(fa.head))(Cofree.apply(_, tl)))
}
private trait CofreeTraverse1[F[_]] extends Traverse1[Cofree[F, *]] with CofreeTraverse[F] with CofreeFoldable1[F]{
implicit def F: Traverse1[F]
override def traverse1Impl[G[_], A, B](fa: Cofree[F,A])(f: A => G[B])(implicit G: Apply[G]): G[Cofree[F,B]] =
G.apply2(f(fa.head), F.traverse1(fa.tail)(traverse1(_)(f)))(Cofree(_, _))
}
private trait CofreeEqual[F[_], A] extends Equal[Cofree[F, A]] {
protected[this] def A: Equal[A]
protected[this] def F: Equal[F[Cofree[F, A]]]
override final def equal(x: Cofree[F, A], y: Cofree[F, A]) = {
A.equal(x.head, y.head) && F.equal(x.tail, y.tail)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy