Skip to content

Commit

Permalink
Merge pull request #1647 from jbgi/instanceof-class
Browse files Browse the repository at this point in the history
Type classes: use standard inheritance but hide it
  • Loading branch information
TomasMikula committed Feb 10, 2018
2 parents 3011709 + f0fb9f5 commit 3aa3166
Show file tree
Hide file tree
Showing 80 changed files with 472 additions and 626 deletions.
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

0 comments on commit 3aa3166

Please sign in to comment.