Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type classes: expose super class functions in sub classes. (WIP) #1

Open
wants to merge 3 commits into
base: noclass
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions base/shared/src/main/scala/scalaz/BaseHierarchy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ object BaseHierarchy {
implicit def choiceProfunctor[P[_, _]](implicit P: Choice[P]): Profunctor[P] = P.profunctor
implicit def monadBind[M[_]](implicit M: Monad[M]): Bind[M] = M.bind
implicit def monadApplicative[M[_]](implicit M: Monad[M]): Applicative[M] = M.applicative
implicit def monadApply[M[_]](implicit M: Monad[M]): Apply[M] = M.applicative.apply
implicit def monadFunctor[M[_]](implicit M: Monad[M]): Functor[M] = M.applicative.apply.functor
implicit def monadApply[M[_]](implicit M: Monad[M]): Apply[M] = M.apply
implicit def monadFunctor[M[_]](implicit M: Monad[M]): Functor[M] = M.functor
implicit def monoidSemigroup[A](implicit A: Monoid[A]): Semigroup[A] = A.semigroup
implicit def traversableFoldable[T[_]](implicit T: Traversable[T]): Foldable[T] = T.foldable
implicit def categoryComposable[=>:[_,_]](implicit C: Category[=>:]): Compose[=>:] = C.compose
Expand All @@ -17,13 +17,13 @@ object BaseHierarchy {

trait BH1 extends BH2 {
implicit def bindApply[M[_]](implicit M: Bind[M]): Apply[M] = M.apply
implicit def bindFunctor[M[_]](implicit M: Bind[M]): Functor[M] = M.apply.functor
implicit def bindFunctor[M[_]](implicit M: Bind[M]): Functor[M] = M.functor
implicit def strongProfunctor[P[_, _]](implicit P: Strong[P]): Profunctor[P] = P.profunctor
}

trait BH2 extends BH3 {
implicit def applicativeApply[M[_]](implicit M: Applicative[M]): Apply[M] = M.apply
implicit def applicativeFunctor[M[_]](implicit M: Applicative[M]): Functor[M] = M.apply.functor
implicit def applicativeFunctor[M[_]](implicit M: Applicative[M]): Functor[M] = M.functor
}

trait BH3 extends BH4 {
Expand Down
19 changes: 10 additions & 9 deletions base/shared/src/main/scala/scalaz/Prelude.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,49 @@ package scalaz

trait BaseTypeclasses {
type Applicative[F[_]] = typeclass.Applicative[F]
val Applicative = typeclass.Applicative
type Apply[F[_]] = typeclass.Apply[F]
val Apply = typeclass.Apply
type Bind[M[_]] = typeclass.Bind[M]
val Bind = typeclass.Bind
type Category[=>:[_,_]] = typeclass.Category[=>:]
type Choice[P[_,_]] = typeclass.Choice[P]
type Cobind[F[_]] = typeclass.Cobind[F]
type Comonad[F[_]] = typeclass.Comonad[F]
type Compose[P[_,_]] = typeclass.Compose[P]
type Foldable[T[_]] = typeclass.Foldable[T]
val Foldable = typeclass.Foldable
type Functor[F[_]] = typeclass.Functor[F]
val Functor = typeclass.Functor
type InvariantFunctor[F[_]] = typeclass.InvariantFunctor[F]
type IsContravariant[F[_]] = typeclass.IsContravariant[F]
type IsCovariant[F[_]] = typeclass.IsCovariant[F]
type Monad[M[_]] = typeclass.Monad[M]
val Monad = typeclass.Monad
type Monoid[T] = typeclass.Monoid[T]
val Monoid = typeclass.Monoid
type Phantom[F[_]] = typeclass.Phantom[F]
type Profunctor[F[_,_]] = typeclass.Profunctor[F]
type Semigroup[T] = typeclass.Semigroup[T]
val Semigroup = typeclass.Semigroup
type Show[A] = typeclass.Show[A]
type Strong[F[_,_]] = typeclass.Strong[F]
type Traversable[T[_]] = typeclass.Traversable[T]
val Traversable = typeclass.Traversable


def Applicative[F[_]](implicit F: Applicative[F]): Applicative[F] = F
def Apply[F[_]](implicit F: Apply[F]): Apply[F] = F
def Bind[F[_]](implicit F: Bind[F]): Bind[F] = F
def Category[=>:[_,_]](implicit P: Category[=>:]): Category[=>:] = P
def Choice[P[_,_]](implicit P: Choice[P]): Choice[P] = P
def Cobind[F[_]](implicit F: Cobind[F]): Cobind[F] = F
def Comonad[F[_]](implicit F: Comonad[F]): Comonad[F] = F
def Compose[P[_,_]](implicit P: Compose[P]): Compose[P] = P
def Foldable[F[_]](implicit F: Foldable[F]): Foldable[F] = F
def Functor[F[_]](implicit F: Functor[F]): Functor[F] = F
def InvariantFunctor[F[_]](implicit F: InvariantFunctor[F]): InvariantFunctor[F] = F
def IsContravariant[F[_]](implicit F: IsContravariant[F]): IsContravariant[F] = F
def IsCovariant[F[_]](implicit F: IsCovariant[F]): IsCovariant[F] = F
def Monad[M[_]](implicit M: Monad[M]): Monad[M] = M
def Monoid[T](implicit T: Monoid[T]): Monoid[T] = T
def Phantom[F[_]](implicit F: Phantom[F]): Phantom[F] = F
def Profunctor[P[_,_]](implicit P: Profunctor[P]): Profunctor[P] = P
def Semigroup[T](implicit T: Semigroup[T]): Semigroup[T] = T
def Show[A](implicit A: Show[A]): Show[A] = A
def Strong[P[_,_]](implicit P: Strong[P]): Strong[P] = P
def Traversable[T[_]](implicit T: Traversable[T]): Traversable[T] = T
}

trait BaseData {
Expand Down
57 changes: 34 additions & 23 deletions base/shared/src/main/scala/scalaz/data/ConstInstances.scala
Original file line number Diff line number Diff line change
@@ -1,50 +1,61 @@
package scalaz
package data

import typeclass.{FoldableClass, TraversableClass}

import Prelude._
import FoldableClass._
import TraversableClass._

trait ConstInstances {
implicit def constTraverse[R]: Traversable[Const[R, ?]] = new TraversableClass[Const[R, ?]] with FoldRight[Const[R, ?]] with Traverse[Const[R, ?]] {
def map[A, B](ma: Const[R, A])(f: A => B): Const[R, B] = ma.retag
implicit def constTraverse[R]: Traversable[Const[R, ?]] = new Traversable.Template[Const[R, ?]] with Traversable.DeriveSequence[Const[R, ?]] with Foldable.DeriveFoldMap[Const[R, ?]] with ConstFunctor[R] {

def traverse[F[_], A, B](ta: Const[R, A])(f: A => F[B])(implicit F: Applicative[F]): F[Const[R, B]] =
override def traverse[F[_], A, B](ta: Const[R, A])(f: A => F[B])(implicit F: Applicative[F]): F[Const[R, B]] =
F.pure(ta.retag)

def foldLeft[A, B](fa: Const[R, A], z: B)(f: (B, A) => B): B = z
override def foldLeft[A, B](fa: Const[R, A], z: B)(f: (B, A) => B): B = z

def foldRight[A, B](fa: Const[R, A], z: => B)(f: (A, => B) => B): B = z
override def foldRight[A, B](fa: Const[R, A], z: => B)(f: (A, => B) => B): B = z

override def toList[A](fa: Const[R, A]): List[A] = Nil
}

implicit def constFunctor[R]: Functor[Const[R, ?]] = new Functor[Const[R, ?]] {
def map[A, B](fa: Const[R, A])(f: A => B): Const[R, B] =
private trait ConstFunctor[R] extends Functor.Template[Const[R, ?]] {
final override def map[A, B](fa: Const[R, A])(f: A => B): Const[R, B] =
fa.retag[B]
}

implicit def constApply[R](implicit R: Semigroup[R]): Apply[Const[R, ?]] = new Apply[Const[R, ?]] {
def functor: Functor[Const[R, ?]] = Const.constFunctor[R]
def ap[A, B](fa: Const[R, A])(f: Const[R, A => B]): Const[R, B] =
private trait ConstApply[R] extends Apply.Template[Const[R, ?]] with ConstFunctor[R] {
def R: Semigroup.Class[R]
final override def ap[A, B](fa: Const[R, A])(f: Const[R, A => B]): Const[R, B] =
Const(R.append(fa.getConst, f.getConst))
}

implicit def constApplicative[R](implicit R: Monoid[R]): Applicative[Const[R, ?]] = new Applicative[Const[R, ?]] {
def apply: Apply[Const[R, ?]] = Const.constApply[R]
def pure[A](a: A): Const[R, A] = Const(R.empty)
private trait ConstApplicative[R] extends Applicative.Template[Const[R, ?]] with ConstApply[R] {
override def R: Monoid.Class[R]
final override def pure[A](a: A): Const[R, A] = Const(R.empty)
}

implicit def constSemigroup[A, B](implicit A: Semigroup[A]): Semigroup[Const[A, B]] = new Semigroup[Const[A, B]] {
def append(a1: Const[A, B], a2: => Const[A, B]): Const[A, B] =
private trait ConstSemigroup[A, B] extends Semigroup.Template[Const[A, B]] {
def A: Semigroup.Class[A]
final override def append(a1: Const[A, B], a2: => Const[A, B]): Const[A, B] =
Const(A.append(a1.getConst, a2.getConst))
}

implicit def constMonoid[A, B](implicit A: Monoid[A]): Monoid[Const[A, B]] = new Monoid[Const[A, B]] {
def semigroup: Semigroup[Const[A, B]] = implicitly
def empty: Const[A, B] = Const(A.empty)
private trait ConstMonoid[A, B] extends Monoid.Template[Const[A, B]] with ConstSemigroup[A, B] {
override def A: Monoid.Class[A]
final override def empty: Const[A, B] = Const(A.empty)
}

implicit def constApply[R: Semigroup]: Apply[Const[R, ?]] = new ConstApply[R] {
override val R = implicitly
}

implicit def constApplicative[R: Monoid]: Applicative[Const[R, ?]] = new ConstApplicative[R] {
override val R = implicitly
}

implicit def constSemigroup[A: Semigroup, B]: Semigroup[Const[A, B]] = new ConstSemigroup[A, B] {
override val A = implicitly
}

implicit def constMonoid[A: Monoid, B]: Monoid[Const[A, B]] = new ConstMonoid[A, B] {
override val A = implicitly
}

implicit def constShow[A, B](implicit A: Show[A]): Show[Const[A, B]] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package scalaz
package data

import typeclass.MonadClass

trait DisjunctionInstances {
implicit def disjunctionMonad[L]: Monad[L \/ ?] = new MonadClass.Template[L \/ ?] {
implicit def disjunctionMonad[L]: Monad[L \/ ?] = new Monad.Template[L \/ ?] with Bind.DeriveFlatten[L \/ ?] {

override def map[A, B](ma: L \/ A)(f: A => B): L \/ B =
ma.fold[L \/ B](l => -\/(l))(r => \/-(f(r)))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package scalaz
package data

import typeclass.MonadClass

trait IdentityInstances {
implicit val monad: Monad[Identity] = new MonadClass[Identity] {
implicit val monad: Monad[Identity] = new Monad.Template[Identity] {
override def map[A, B](fa: Identity[A])(f: A => B): Identity[B] = Identity(f(fa.run))
override def ap[A, B](fa: Identity[A])(f: Identity[A => B]): Identity[B] = Identity(f.run.apply(fa.run))
override def ap[A, B](fa: Identity[A])(f: Identity[A => B]): Identity[B] = Identity(f.run(fa.run))
override def pure[A](a: A): Identity[A] = Identity(a)
override def flatMap[A, B](oa: Identity[A])(f: A => Identity[B]): Identity[B] = f(oa.run)
override def flatten[A](ma: Identity[Identity[A]]): Identity[A] = ma.run
Expand Down
9 changes: 3 additions & 6 deletions base/shared/src/main/scala/scalaz/data/Maybe.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package scalaz
package data

import typeclass.{MonadClass, TraversableClass}
import typeclass.FoldableClass._

sealed trait MaybeModule {
type Maybe[A]

Expand Down Expand Up @@ -60,7 +57,7 @@ private[scalaz] object MaybeImpl extends MaybeModule {
}

private val instance =
new MonadClass.Template[Maybe] with TraversableClass[Maybe] with FoldRight[Maybe] {
new Monad.Template[Maybe] with Bind.DeriveFlatten[Maybe] with Traversable.Template[Maybe] with Foldable.DeriveFoldMap[Maybe] {

override def ap[A, B](ma: Maybe[A])(mf: Maybe[A => B]): Maybe[B] =
mf match {
Expand All @@ -79,13 +76,13 @@ private[scalaz] object MaybeImpl extends MaybeModule {

override def traverse[F[_], A, B](ma: Maybe[A])(f: A => F[B])(implicit F: Applicative[F]): F[Maybe[B]] =
ma match {
case Some(a) => F.apply.functor.map(f(a))(just)
case Some(a) => F.map(f(a))(just)
case None => F.pure(None)
}

override def sequence[F[_], A](ma: Maybe[F[A]])(implicit F: Applicative[F]): F[Maybe[A]] =
ma match {
case Some(fa) => F.apply.functor.map(fa)(just)
case Some(fa) => F.map(fa)(just)
case None => F.pure(None)
}

Expand Down
4 changes: 2 additions & 2 deletions base/shared/src/main/scala/scalaz/data/These.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ sealed abstract class These[L, R] {
/* Traversable (on the right) */
final def traverse[F[_], B](f: R => F[B])(implicit F: Applicative[F]): F[These[L, B]] = this match {
case thiz @ This(_) => F.pure(thiz.pmap[B])
case That(right) => F.apply.functor.map(f(right))(That(_))
case Both(left, right) => F.apply.functor.map(f(right))(Both(left, _))
case That(right) => F.map(f(right))(That(_))
case Both(left, right) => F.map(f(right))(Both(left, _))
}

/* Semigroup */
Expand Down
11 changes: 4 additions & 7 deletions base/shared/src/main/scala/scalaz/data/TheseInstances.scala
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package scalaz
package data

import typeclass.{ BindClass, FoldableClass, MonadClass, SemigroupClass, TraversableClass }

trait TheseInstances {
// implicit def bifunctor: Bifunctor[These] = ...

implicit final def theseMonad[L: Semigroup]: Monad[These[L, ?]] =
new MonadClass.Template[These[L, ?]] with BindClass.Ap[These[L, ?]] {
new Monad.Template[These[L, ?]] with Bind.DeriveAp[These[L, ?]] with Bind.DeriveFlatten[These[L, ?]] {
override def map[A, B](ma: These[L, A])(f: A => B) = ma.rmap(f)
def flatMap[A, B](ma: These[L, A])(f: A => These[L, B]) = ma.flatMap(f)
def pure[A](a: A) = That(a)
}

implicit final def theseTraversable[L]: Traversable[These[L, ?]] =
new TraversableClass[These[L, ?]]
with TraversableClass.Traverse[These[L, ?]]
with FoldableClass.FoldMap[These[L, ?]] {
new Traversable.Template[These[L, ?]]
with Traversable.DeriveSequence[These[L, ?]] with Foldable.DeriveToList[These[L, ?]] {
def traverse[F[_]: Applicative, A, B](ta: These[L, A])(f: A => F[B]) = ta.traverse(f)
def foldMap[A, B: Monoid](fa: These[L, A])(f: A => B) = fa.foldMap(f)
def map[A, B](ma: These[L, A])(f: A => B) = ma.rmap(f)
Expand All @@ -27,7 +24,7 @@ trait TheseInstances {
}

implicit final def theseSemigroup[L: Semigroup, R: Semigroup]: Semigroup[These[L, R]] =
new SemigroupClass[These[L, R]] {
new Semigroup.Template[These[L, R]] {
def append(a1: These[L, R], a2: => These[L, R]) = a1.append(a2)
}

Expand Down
24 changes: 20 additions & 4 deletions base/shared/src/main/scala/scalaz/typeclass/Applicative.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
package scalaz
package typeclass

trait Applicative[F[_]] {
def apply: Apply[F]
def pure[A](a: A): F[A]
}
sealed trait Applicative[F[_]] extends Applicative.Class[F]

object Applicative {

trait Class[F[_]] extends Apply.Class[F] {
def pure[A](a: A): F[A]

def applicative: Applicative[F]
}

trait Template[F[_]] extends Apply.Template[F] with Applicative[F] {
final override def applicative = this
}

trait DeriveMap[F[_]] extends Monad.Alt[DeriveMap[F]] { self: Class[F] =>
final override def map[A, B](ma: F[A])(f: (A) => B): F[B] = ap(ma)(pure(f))
}

def apply[F[_]](implicit F: Applicative[F]): Applicative[F] = F
}
14 changes: 0 additions & 14 deletions base/shared/src/main/scala/scalaz/typeclass/ApplicativeClass.scala

This file was deleted.

20 changes: 16 additions & 4 deletions base/shared/src/main/scala/scalaz/typeclass/Apply.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package scalaz
package typeclass

trait Apply[F[_]] {
def functor: Functor[F]
def ap[A, B](fa: F[A])(f: F[A => B]): F[B]
}
sealed trait Apply[F[_]] extends Apply.Class[F]

object Apply {

trait Class[F[_]] extends Functor.Class[F] {
def ap[A, B](fa: F[A])(f: F[A => B]): F[B]

def apply: Apply[F]
}

trait Template[F[_]] extends Functor.Template[F] with Apply[F] {
final override def apply = this
}

def apply[F[_]](implicit F: Apply[F]): Apply[F] = F
}
6 changes: 0 additions & 6 deletions base/shared/src/main/scala/scalaz/typeclass/ApplyClass.scala

This file was deleted.

34 changes: 29 additions & 5 deletions base/shared/src/main/scala/scalaz/typeclass/Bind.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
package scalaz
package typeclass

trait Bind[M[_]] {
def apply: Apply[M]
def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B]
def flatten[A](ma: M[M[A]]): M[A]
}
sealed trait Bind[M[_]] extends Bind.Class[M]

object Bind {

trait Class[M[_]] extends Apply.Class[M] {
def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B]
def flatten[A](ma: M[M[A]]): M[A]

def bind: Bind[M]
}

trait Template[M[_]] extends Apply.Template[M] with Bind[M] {
final override def bind = this
}

trait DeriveAp[M[_]] extends Monad.Alt[DeriveAp[M]] { self: Class[M] =>
final override def ap[A, B](fa: M[A])(f: M[A => B]): M[B] = flatMap(f)(map(fa))
}

trait Alt[D <: Alt[D]]
trait DeriveFlatten[M[_]] extends Alt[DeriveFlatten[M]] { self: Class[M] =>
final override def flatten[A](ma: M[M[A]]): M[A] = flatMap(ma)(identity)
}
trait DeriveFlatMap[M[_]] extends Alt[DeriveFlatMap[M]] { self: Class[M] =>
final override def flatMap[A, B](ma: M[A])(f: (A) => M[B]): M[B] = flatten(map(ma)(f))
}

def apply[F[_]](implicit F: Bind[F]): Bind[F] = F
}
Loading