All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.Recursion.scala Maven / Gradle / Ivy

The newest version!
package scalaz

import Scalaz._
import Liskov._
import scala.annotation.unchecked.uncheckedVariance

/**
 * Possibly negative corecursion 
 */
trait Nu_[F[_]] extends Immutable {
  def out: F[Nu_[F]]
}
object Nu_ { 
  def apply[F[_]](v: => F[Nu_[F]]) : Nu_[F] = new Nu_[F] { def out = v }
  def unapply[F[_]](v: Nu_[F]) = Some(v.out)
  implicit def unwrap[F[_]](v: Nu_[F]) = v.out
}

/** 
 * Possibly negative recursion. 
 * Note Mu_ is not a subtype of Nu_, because generating Nu_[F] from Mu_[F] 
 * requires a Functor for F or subtyping.
 */
trait Mu_[F[_]] extends Immutable {
  val out: F[Mu_[F]]
}
object Mu_ { 
  def apply[F[_]](v: F[Mu_[F]]) : Mu_[F] = new Mu_[F] { val out = v }
  def unapply[F[_]](v: Mu_[F]) = Some(v.out)
  implicit def unwrap[F[_]](v: Mu_[F]) = v.out
} 

/** Positive corecursion */
// This works in Scala 2.9+, but not used yet until we stop supporting 2.8.1
//trait Nu[+F[+_]] extends Nu_[F @uncheckedVariance] {

trait Nu[F[+_]] extends Nu_[F] {
  def out: F[Nu[F]]
}
object Nu { 
  def apply[F[+_]](v: => F[Nu[F]]) : Nu[F] = new Nu[F] { def out = v }
  def unapply[F[+_]](v : Nu[F]) = Some(v.out)
  implicit def rewrap[F[+_],G[+_]](v : Nu[F])(
    implicit lt: F[Nu[F]] <~< G[Nu[F]]
  ) : Nu[G] = v.asInstanceOf[Nu[G]]
  implicit def unwrap[F[_]](v: Mu_[F]) = v.out
}

/** Positive recursion */
// This works in Scala 2.9+, but not used yet until we stop supporting 2.8.1
// trait Mu[+F[+_]] extends Nu[F] with Mu_[F @uncheckedVariance] {
trait Mu[F[+_]] extends Nu[F] with Mu_[F] {
  val out: F[Mu[F]]
}
object Mu {
  def apply[F[+_]](v: F[Mu[F]]) : Mu[F] = new Mu[F] { val out = v } 
  def unapply[F[+_]](v: Mu[F]) = Some(v.out)
  implicit def rewrap[F[+_],G[+_]](v : Mu[F])(
    implicit lt: F[Mu[F]] <~< G[Mu[F]]
  ) : Mu[G] = v.asInstanceOf[Mu[G]]
  implicit def unwrap[F[+_]](v: Mu[F]) = v.out
}

/** Cofree corecursion */
trait Cofree_[F[_],A] extends Immutable {
  val extract: A
  def out: F[Cofree_[F,A]]
  def scanr[B](g: (A, F[Cofree_[F,B]]) => B)(implicit f: Functor[F]): Cofree_[F, B] = {
    lazy val qs = out map (_.scanr(g))
    Cofree_[F, B](g(extract, qs), qs)
  }
}
object Cofree_ {
  def apply[F[_],A](
    a: A,
    v: => F[Cofree_[F,A]]
  ) : Cofree_[F,A] = 
  new Cofree_[F,A] {
    val extract = a
    def out = v
  }
  def unapply[F[_],A](v: Cofree_[F,A]) = Some((v.extract, v.out))
  implicit def unwrap[F[_],A](v: Cofree_[F,A]) = (v.extract, v.out)

  implicit def Cofree_Traverse[T[+_]:Traverse]
    : Traverse[({type λ[α]=Cofree_[T, α]})#λ] =
  new Traverse[({type λ[α]=Cofree_[T, α]})#λ] {
    def traverse[F[_]: Applicative, A, B](f : A => F[B], t : Cofree_[T,A]) : F[Cofree_[T,B]] = { 
       (f(t.extract) <**> t.out.traverse(traverse(f,_)))((a, o) => Cofree_(a,o))
    }
  }
}

/** Positive cofree corecursion */
// This works in Scala 2.9+, but not used yet until we stop supporting 2.8.1
// trait Cofree[+F[+_],+A] extends Nu[F] with Cofree_[F @uncheckedVariance, A @uncheckedVariance] {
trait Cofree[F[+_],A] extends Nu[F] with Cofree_[F,A] {

  val extract: A 
  def out: F[Cofree[F,A]]
  def scanr[B](g: (A, F[Cofree[F,B]]) => B)(implicit f: Functor[F]): Cofree[F, B] = {
    lazy val qs = out map ((_: Cofree[F,A]).scanr(g)(f))
    Cofree[B, F](g(extract, qs), qs)
  }
}
object Cofree { 
  def apply[A,F[+_]](
    a: A,
    v: => F[Cofree[F,A]]
  ) : Cofree[F,A] = 
  new Cofree[F,A] {
    val extract = a
    def out = v
  }
  def unapply[F[+_],A](v: Cofree[F,A]) = Some((v.extract, v.out))
  implicit def rewrap[F[+_],G[+_],A,B >: A](v : Cofree[F,A])(
    implicit lt: F[Cofree[F,A]] <~< G[Cofree[F,A]]
  ) : Cofree[G,B] = v.asInstanceOf[Cofree[G,B]]
  implicit def unwrap[F[+_],A](v: Cofree[F,A]) = (v.extract, v.out)

  implicit def CofreeTraverse[T[+_]:Traverse]
    : Traverse[({type λ[α]=Cofree[T, α]})#λ] =
  new Traverse[({type λ[α]=Cofree[T, α]})#λ] {
    def traverse[F[_]: Applicative, A, B](f : A => F[B], t : Cofree[T,A]) : F[Cofree[T,B]] = { 
       (f(t.extract) <**> t.out.traverse(traverse(f,_)))((a, o) => Cofree(a,o))
    }
  }
}

/** Cofree recursion */
trait CofreeRec_[F[_],A] {
  val extract: A
  val out: F[CofreeRec_[F,A]]
}
object CofreeRec_ { 
  def apply[F[_],A](
    a: A,
    v: => F[CofreeRec_[F,A]]
  ) : CofreeRec_[F,A] = 
  new CofreeRec_[F,A] {
    val extract = a
    val out = v
  }
  def unapply[F[_],A](v: CofreeRec_[F,A]) = Some((v.extract, v.out))
  implicit def unwrap[F[_],A](v: CofreeRec_[F,A]) = (v.extract, v.out)

  implicit def CofreeRec_Traverse[T[+_]:Traverse]
    : Traverse[({type λ[α]=CofreeRec_[T, α]})#λ] =
  new Traverse[({type λ[α]=CofreeRec_[T, α]})#λ] {
    def traverse[F[_]: Applicative, A, B](f : A => F[B], t : CofreeRec_[T,A]) : F[CofreeRec_[T,B]] = { 
       (f(t.extract) <**> t.out.traverse(traverse(f,_)))((a, o) => CofreeRec_(a,o))
    }
  }
}

/** Positive cofree recursion */

// ideal: trait CofreeRec[+F[+_],A] extends Mu[F] with CofreeRec_[F,A] {
// works: trait CofreeRec[+F[+_],A] extends Mu[F] {
trait CofreeRec[F[+_],A] extends Mu[F] with CofreeRec_[F,A] {
  val extract: A
  val out: F[CofreeRec[F,A]]
}
object CofreeRec { 
  def apply[F[+_],A](
    a: A,
    v: => F[CofreeRec[F,A]]
  ) : CofreeRec[F,A] = 
  new CofreeRec[F,A] {
    val extract = a
    val out = v
  }
  def unapply[F[+_],A](v: CofreeRec[F,A]) = Some((v.extract, v.out))
  implicit def rewrap[F[+_],G[+_],A,B >: A](v : CofreeRec[F,A])(
    implicit lt: F[CofreeRec[F,A]] <~< G[CofreeRec[F,A]]
  ) : CofreeRec[G,B] = v.asInstanceOf[CofreeRec[G,A]]
  implicit def unwrap[F[+_],A](v: CofreeRec[F,A]) = (v.extract, v.out)

  implicit def CofreeRecTraverse[T[+_]:Traverse]
    : Traverse[({type λ[α]=CofreeRec[T, α]})#λ] =
  new Traverse[({type λ[α]=CofreeRec[T, α]})#λ] {
    def traverse[F[_]: Applicative, A, B](f : A => F[B], t : CofreeRec[T,A]) : F[CofreeRec[T,B]] = { 
       (f(t.extract) <**> t.out.traverse(traverse(f,_)))((a, o) => CofreeRec(a,o))
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy