Created
October 1, 2012 03:17
-
-
Save eed3si9n/3809290 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package scalaz | |
package typelevel | |
/** | |
* Represents a function `A => F[B]` where `[F: TC]`. | |
*/ | |
trait Func[F[_], TC[F[_]] <: Functor[F], A, B] { self => | |
def runA(a: A): F[B] | |
implicit def TC: KTypeClass[TC] | |
implicit def F: TC[F] | |
import Func._ | |
import syntax.HLists._ | |
import Leibniz.=== | |
// /** alias for andThenA */ | |
// def @>>>[G[_], C](g: Func[G, TC, B, C]) = andThenA(g) | |
// /** compose `A => F[B]` and `B => G[C]` into `A => F[G[C]]` */ | |
// def andThenA[G[_], C](g: Func[G, TC, B, C]) = g.composeA(self) | |
// /** alias for composeA */ | |
// def <<<@[G[_], C](g: Func[G, TC, C, A]) = composeA(g) | |
// /** compose `A => F[B]` and `C => G[A]` into `C => G[F[B]]` */ | |
// def composeA[G[_], C](g: Func[G, TC, C, A]): Func[({type λ[α] = G[F[α]]})#λ, TC, C, B] = new Func[({type λ[α] = G[F[α]]})#λ, TC, C, B] { | |
// def runA(c: C): G[F[B]] = g.F.map(g.runA(c): G[A]) { a: A => self.runA(a) } | |
// def TC = self.TC | |
// // def F = g.F compose self.F | |
// } | |
/** alias for productA */ | |
def @&&&[G[_]](g: Func[G, TC, A, B]) = productA(g) | |
def &&&@[G[_]](g: Func[G, TC, A, B]) = g.productA(self) | |
/** compose `A => F[B]` and `A => G[B]` into `A => (F[B], G[B])` */ | |
def productA[G[_]](g: Func[G, TC, A, B]): Func[TCCons[F, TCCons[G, TCNil]]#Product, TC, A, B] = new Func[TCCons[F, TCCons[G, TCNil]]#Product, TC, A, B] { | |
def runA(a: A) = self.runA(a) :: g.runA(a) :: HNil | |
def F = (self.F *: g.F *: TC.emptyProduct).instance | |
def TC = self.TC | |
} | |
def mapA[C](f: B => C): Func[F, TC, A, C] = | |
func(a => F.map(self.runA(a))(f)) | |
def traverse[G[_]](value: G[A])(implicit G: Traverse[G], ev: TC[F] === Applicative[F]): F[G[B]] = | |
G.traverse(value)(a => self.runA(a))(F.asInstanceOf[Applicative[F]]) | |
} | |
// | |
// Prioritized Implicits for type class instances | |
// | |
trait FuncInstances3 { | |
implicit def FuncFunctor[F[_], TC[X[_]] <: Functor[X], R]: Functor[({type λ[α] = Func[F, TC, R, α]})#λ] = new FuncFunctor[F, TC, R] {} | |
} | |
trait FuncInstances2 extends FuncInstances3 { | |
implicit def FuncPointed[F[_], TC[F[_]] <: Pointed[F], R](implicit TC0: KTypeClass[TC], F0: TC[F]): Pointed[({type λ[α] = Func[F, TC, R, α]})#λ] = new FuncPointed[F, TC, R] { | |
implicit def TC: KTypeClass[TC] = TC0 | |
implicit def F: TC[F] = F0 | |
} | |
implicit def FuncApply[F[_], TC[F[_]] <: Apply[F], R](implicit TC0: KTypeClass[TC], F0: TC[F]): Apply[({type λ[α] = Func[F, TC, R, α]})#λ] = new FuncApply[F, TC, R] { | |
implicit def TC: KTypeClass[TC] = TC0 | |
implicit def F: TC[F] = F0 | |
} | |
} | |
trait FuncInstances1 extends FuncInstances2 { | |
implicit def FuncApplicative[F[_], TC[F[_]] <: Applicative[F], R](implicit TC0: KTypeClass[TC], F0: TC[F]): Applicative[({type λ[α] = Func[F, TC, R, α]})#λ] = new FuncApplicative[F, TC, R] { | |
implicit def TC: KTypeClass[TC] = TC0 | |
implicit def F: TC[F] = F0 | |
} | |
} | |
trait FuncInstances extends FuncInstances1 { | |
} | |
trait FuncFunctions { | |
def func[M[_], TC[M[_]] <: Functor[M], A, B](f: A => M[B])(implicit TC0: KTypeClass[TC], F0: TC[M]): Func[M, TC, A, B] = new Func[M, TC, A, B] { | |
def TC = TC0 | |
def F = F0 | |
def runA(a: A) = f(a) | |
} | |
def functorfunc[M[_], A, B](f: A => M[B])(implicit F0: Functor[M]): Func[M, Functor, A, B] = func[M, Functor, A, B](f) | |
def pointedfunc[M[_], A, B](f: A => M[B])(implicit F0: Pointed[M]): Func[M, Pointed, A, B] = func[M, Pointed, A, B](f) | |
def applyfunc[M[_], A, B](f: A => M[B])(implicit F0: Apply[M]): Func[M, Apply, A, B] = func[M, Apply, A, B](f) | |
def appfunc[M[_], A, B](f: A => M[B])(implicit F0: Applicative[M]): Func[M, Applicative, A, B] = func[M, Applicative, A, B](f) | |
def appfuncU[A, R](f: A => R)(implicit F0: Unapply[Applicative, R]): Func[F0.M, Applicative, A, F0.A] = new Func[F0.M, Applicative, A, F0.A] { | |
def TC = KTypeClass[Applicative] | |
def F = F0.TC | |
def runA(a: A) = F0(f(a)) | |
} | |
} | |
object Func extends FuncFunctions with FuncInstances { | |
def apply[M[_], TC[M[_]] <: Functor[M], A, B](f: A => M[B])(implicit TC0: KTypeClass[TC], F0: TC[M]): Func[M, TC, A, B] = func(f) | |
} | |
object AppFuncU { | |
def apply[A, R](f: A => R)(implicit F0: Unapply[Applicative, R]): Func[F0.M, Applicative, A, F0.A] = Func.appfuncU(f) | |
} | |
// | |
// Implementation traits for type class instances | |
// | |
import Func._ | |
private[scalaz] trait FuncFunctor[F[_], TC[F[_]] <: Functor[F], R] extends Functor[({type λ[α] = Func[F, TC, R, α]})#λ] { | |
override def map[A, B](fa: Func[F, TC, R, A])(f: A => B): Func[F, TC, R, B] = fa mapA f | |
} | |
private[scalaz] trait FuncPointed[F[_], TC[F[_]] <: Pointed[F], R] extends Pointed[({type λ[α] = Func[F, TC, R, α]})#λ] with FuncFunctor[F, TC, R] { | |
implicit def TC: KTypeClass[TC] | |
implicit def F: TC[F] | |
def point[A](a: => A): Func[F, TC, R, A] = func((r: R) => F.point(a)) | |
} | |
private[scalaz] trait FuncApply[F[_], TC[F[_]] <: Apply[F], R] extends Apply[({type λ[α] = Func[F, TC, R, α]})#λ] with FuncFunctor[F, TC, R] { | |
implicit def TC: KTypeClass[TC] | |
implicit def F: TC[F] | |
def ap[A, B](fa: => Func[F, TC, R, A])(f: => Func[F, TC, R, (A) => B]): Func[F, TC, R, B] = func(r => F.ap(fa.runA(r))(f.runA(r))) | |
} | |
private[scalaz] trait FuncApplicative[F[_], TC[F[_]] <: Applicative[F], R] extends Applicative[({type λ[α] = Func[F, TC, R, α]})#λ] with FuncApply[F, TC, R] with FuncPointed[F, TC, R] { | |
implicit def TC: KTypeClass[TC] | |
implicit def F: TC[F] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Are you sure the
asInstanceOf
is necessary? You can useev
to safely convertF
.