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: use standard inheritance but hide it #1647

Merged
merged 1 commit into from
Feb 10, 2018
Merged
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
33 changes: 17 additions & 16 deletions base/shared/src/main/scala/scalaz/BaseHierarchy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,35 @@ package scalaz
trait BaseHierarchy extends BaseHierarchy.BH0

object BaseHierarchy {

trait BH0 extends BH1 {
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 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
implicit def comonadCobind[F[_]](implicit F: Comonad[F]): Cobind[F] = F.cobind
implicit def choiceProfunctor[P[_, _]](implicit P: Choice[P]): Profunctor[P] = instanceOf(P)
implicit def monadBind[M[_]](implicit M: Monad[M]): Bind[M] = instanceOf(M)
implicit def monadApplicative[M[_]](implicit M: Monad[M]): Applicative[M] = instanceOf(M)
implicit def monadApply[M[_]](implicit M: Monad[M]): Apply[M] = instanceOf(M)
implicit def monadFunctor[M[_]](implicit M: Monad[M]): Functor[M] = instanceOf(M)
implicit def monoidSemigroup[A](implicit A: Monoid[A]): Semigroup[A] = instanceOf(A)
implicit def traversableFoldable[T[_]](implicit T: Traversable[T]): Foldable[T] = instanceOf(T)
implicit def categoryComposable[=>:[_,_]](implicit C: Category[=>:]): Compose[=>:] = instanceOf(C)
implicit def comonadCobind[F[_]](implicit F: Comonad[F]): Cobind[F] = instanceOf(F)
}

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 strongProfunctor[P[_, _]](implicit P: Strong[P]): Profunctor[P] = P.profunctor
implicit def bindApply[M[_]](implicit M: Bind[M]): Apply[M] = instanceOf(M)
implicit def bindFunctor[M[_]](implicit M: Bind[M]): Functor[M] = instanceOf(M)
implicit def strongProfunctor[P[_, _]](implicit P: Strong[P]): Profunctor[P] = instanceOf(P)
}

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 applicativeApply[M[_]](implicit M: Applicative[M]): Apply[M] = instanceOf(M)
implicit def applicativeFunctor[M[_]](implicit M: Applicative[M]): Functor[M] = instanceOf(M)
}

trait BH3 extends BH4 {
implicit def applyFunctor[M[_]](implicit M: Apply[M]): Functor[M] = M.functor
implicit def applyFunctor[M[_]](implicit M: Apply[M]): Functor[M] = instanceOf(M)
}

trait BH4 {
implicit def traversableFunctor[T[_]](implicit T: Traversable[T]): Functor[T] = T.functor
implicit def traversableFunctor[T[_]](implicit T: Traversable[T]): Functor[T] = instanceOf(T)
}
}
13 changes: 13 additions & 0 deletions base/shared/src/main/scala/scalaz/InstanceOfModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package scalaz

sealed abstract class InstanceOfModule {
type InstanceOf[T] <: T
def instanceOf[T](t: T): InstanceOf[T]
}

object InstanceOfModule {
val impl : InstanceOfModule = new InstanceOfModule {
override type InstanceOf[T] = T
override def instanceOf[T](t: T) = t
}
}
94 changes: 51 additions & 43 deletions base/shared/src/main/scala/scalaz/Prelude.scala
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
package scalaz

import typeclass._

trait BaseTypeclasses {
type Applicative[F[_]] = typeclass.Applicative[F]
type Apply[F[_]] = typeclass.Apply[F]
type Bind[M[_]] = typeclass.Bind[M]
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]
type Functor[F[_]] = typeclass.Functor[F]
type InvariantFunctor[F[_]] = typeclass.InvariantFunctor[F]
type IsContravariant[F[_]] = typeclass.IsContravariant[F]
type IsCovariant[F[_]] = typeclass.IsCovariant[F]
type Monad[M[_]] = typeclass.Monad[M]
type Monoid[T] = typeclass.Monoid[T]
type Phantom[F[_]] = typeclass.Phantom[F]
type Profunctor[F[_,_]] = typeclass.Profunctor[F]
type Semigroup[T] = typeclass.Semigroup[T]
type Debug[A] = typeclass.Debug[A]
type Strong[F[_,_]] = typeclass.Strong[F]
type Traversable[T[_]] = typeclass.Traversable[T]

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 Debug[A](implicit A: Debug[A]): Debug[A] = A
def Strong[P[_,_]](implicit P: Strong[P]): Strong[P] = P
def Traversable[T[_]](implicit T: Traversable[T]): Traversable[T] = T
type InstanceOf[T] = InstanceOfModule.impl.InstanceOf[T]

@inline
final def instanceOf[T](t: T): InstanceOf[T] = InstanceOfModule.impl.instanceOf(t)

type Applicative[F[_]] = InstanceOf[ApplicativeClass[F]]
type Apply[F[_]] = InstanceOf[ApplyClass[F]]
type Bind[M[_]] = InstanceOf[BindClass[M]]
type Category[=>:[_,_]] = InstanceOf[CategoryClass[=>:]]
type Choice[P[_,_]] = InstanceOf[ChoiceClass[P]]
type Cobind[F[_]] = InstanceOf[CobindClass[F]]
type Comonad[F[_]] = InstanceOf[ComonadClass[F]]
type Compose[P[_,_]] = InstanceOf[ComposeClass[P]]
type Foldable[T[_]] = InstanceOf[FoldableClass[T]]
type Functor[F[_]] = InstanceOf[FunctorClass[F]]
type InvariantFunctor[F[_]] = InstanceOf[InvariantFunctorClass[F]]
type IsContravariant[F[_]] = InstanceOf[IsContravariantClass[F]]
type IsCovariant[F[_]] = InstanceOf[IsCovariantClass[F]]
type Monad[M[_]] = InstanceOf[MonadClass[M]]
type Monoid[T] = InstanceOf[MonoidClass[T]]
type Contravariant[F[_]] = InstanceOf[ContravariantClass[F]]
type Phantom[F[_]] = InstanceOf[PhantomClass[F]]
type Profunctor[F[_,_]] = InstanceOf[ProfunctorClass[F]]
type Semigroup[T] = InstanceOf[SemigroupClass[T]]
type Debug[A] = InstanceOf[DebugClass[A]]
type Strong[F[_,_]] = InstanceOf[StrongClass[F]]
type Traversable[T[_]] = InstanceOf[TraversableClass[T]]

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

trait BaseData {
Expand Down
4 changes: 3 additions & 1 deletion base/shared/src/main/scala/scalaz/data/AMaybeInstances.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package scalaz
package data

import scalaz.typeclass.DebugClass

trait AMaybeInstances {
implicit final def amaybeDebug[F[_, _], A, B](implicit FAB: Debug[F[A, B]]): Debug[AMaybe[F, A, B]] = {
implicit final def amaybeDebug[F[_, _], A, B](implicit FAB: Debug[F[A, B]]): Debug[AMaybe[F, A, B]] = instanceOf[DebugClass[AMaybe[F, A, B]]] {
case AJust(value) => s"AMaybe(${FAB.debug(value)})"
case AEmpty() => "AEmpty()"
}
Expand Down
62 changes: 38 additions & 24 deletions base/shared/src/main/scala/scalaz/data/ConstInstances.scala
Original file line number Diff line number Diff line change
@@ -1,52 +1,66 @@
package scalaz
package data

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

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, ?]] = instanceOf(new TraversableClass.DeriveSequence[Const[R, ?]] with FoldableClass.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 FunctorClass[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 ApplyClass[Const[R, ?]] with ConstFunctor[R] {
def R: SemigroupClass[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 ApplicativeClass[Const[R, ?]] with ConstApply[R] {
override def R: MonoidClass[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 SemigroupClass[Const[A, B]] {
def A: SemigroupClass[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 MonoidClass[Const[A, B]] with ConstSemigroup[A, B] {
override def A: MonoidClass[A]
final override def empty: Const[A, B] = Const(A.empty)
}

implicit def constDebug[A, B](implicit A: Debug[A]): Debug[Const[A, B]] =
implicit def constApply[R: Semigroup]: Apply[Const[R, ?]] = instanceOf(new ConstApply[R] {
override val R = implicitly
})

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

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

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

implicit def constDebug[A, B](implicit A: DebugClass[A]): DebugClass[Const[A, B]] = instanceOf[DebugClass[Const[A, B]]](
a => A.debug(a.getConst)
)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package scalaz
package data

import typeclass.MonadClass
import scalaz.typeclass.{BindClass, DebugClass, MonadClass}

trait DisjunctionInstances {
implicit def disjunctionMonad[L]: Monad[L \/ ?] = new MonadClass.Template[L \/ ?] {
implicit def disjunctionMonad[L]: Monad[L \/ ?] = instanceOf(new MonadClass[L \/ ?] with BindClass.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 All @@ -17,9 +17,9 @@ trait DisjunctionInstances {

override def flatMap[A, B](oa: L \/ A)(f: A => L \/ B): L \/ B =
oa.fold[L \/ B](l => -\/(l))(a => f(a))
}
})

implicit def disjunctionDebug[L, R](implicit L: Debug[L], R: Debug[R]): Debug[L \/ R] = {
implicit def disjunctionDebug[L, R](implicit L: Debug[L], R: Debug[R]): Debug[L \/ R] = instanceOf[DebugClass[L \/ R]] {
case -\/(left) => s"""-\/(${L.debug(left)})"""
case \/-(right) => s"""\/-(${R.debug(right)})"""
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package scalaz
package data

import scalaz.typeclass.ProfunctorClass

trait DownStarInstances {
implicit def downstarProfunctor[F[_]](implicit F: Functor[F]): Profunctor[DownStar[F, ?, ?]] =
new Profunctor[DownStar[F, ?, ?]] {
implicit def downstarProfunctor[F[_]](implicit F: Functor[F]): Profunctor[DownStar[F, ?, ?]] = instanceOf(
new ProfunctorClass[DownStar[F, ?, ?]] {
override def lmap[A, B, C](fab: DownStar[F, A, B])(ca: C => A): DownStar[F, C, B] =
DownStar(fc => fab.run(F.map(fc)(ca)))

Expand All @@ -12,5 +14,5 @@ trait DownStarInstances {

override def dimap[A, B, C, D](fab: DownStar[F, A, B])(ca: C => A)(bd: B => D): DownStar[F, C, D] =
DownStar(fc => bd(fab.run(F.map(fc)(ca))))
}
})
}
4 changes: 2 additions & 2 deletions base/shared/src/main/scala/scalaz/data/ForgetInstances.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package data
import typeclass.StrongClass

trait ForgetInstances { self =>
implicit def strong[A]: Strong[Forget[A, ?, ?]] = new StrongClass.First[Forget[A, ?, ?]] {
implicit def strong[A]: Strong[Forget[A, ?, ?]] = instanceOf(new StrongClass[Forget[A, ?, ?]] {
override def dimap[B, C, D, E](fbc: Forget[A, B, C])(fdb: D => B)(fce: C => E): Forget[A, D, E] =
Forget[A, D, E](fdb andThen fbc.forget)

Expand All @@ -17,6 +17,6 @@ trait ForgetInstances { self =>
override def first[B, C, D](pab: Forget[A, B, C]): Forget[A, (B, D), (C, D)] = Forget[A, (B, D), (C, D)](bd => pab.forget(bd._1))

override def second[B, C, D](pab: Forget[A, B, C]): Forget[A, (D, B), (D, C)] = Forget[A, (D, B), (D, C)](bd => pab.forget(bd._2))
}
})
}

5 changes: 2 additions & 3 deletions base/shared/src/main/scala/scalaz/data/IList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ private[data] object IListImpl extends IListModule {
def uncons[A](as: IList[A]): Maybe2[A, IList[A]] =
Fix.unfix[Maybe2[A, ?]](as)

implicit val isCovariantInstance: IsCovariant[IList] =
new IsCovariantClass[IList] with IsCovariantClass.LiftLiskov[IList] {
implicit val isCovariantInstance: IsCovariant[IList] = instanceOf(new IsCovariantClass.LiftLiskov[IList] {

override def liftLiskov[A, B](implicit ev: A <~< B): IList[A] <~< IList[B] = {
type <~~<[F[_], G[_]] = ∀.Prototype[λ[α => F[α] <~< G[α]]]
val ev1 = Λ[α](Maybe2.isCovariant_1[α].liftLiskov[A, B]): Maybe2[A, ?] <~~< Maybe2[B, ?]
Fix.liftLiskov[Maybe2[A, ?], Maybe2[B, ?]](ev1.make)(Maybe2.isCovariant_2[A])
}
}
})
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package scalaz
package data

import typeclass.MonadClass
import scalaz.typeclass.MonadClass

trait IdentityInstances {
implicit val monad: Monad[Identity] = new MonadClass[Identity] {
implicit val monad: Monad[Identity] = instanceOf(new MonadClass[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
}
})
}
Loading