diff --git a/docs/src/main/tut/guidelines.md b/docs/src/main/tut/guidelines.md index bc7e3b1c17..ed9fd5cfa7 100644 --- a/docs/src/main/tut/guidelines.md +++ b/docs/src/main/tut/guidelines.md @@ -69,7 +69,7 @@ The user doesn't need to specify the type `A` which is given by the parameter. You probably noticed that there is a `val dummy: Boolean` in the `PurePartiallyApplied` class. This is a trick we used to make this intermediate class a [Value Class](http://docs.scala-lang.org/overviews/core/value-classes.html) so that there is no cost of allocation, i.e. at runtime, it doesn't create an instance of `PurePartiallyApplied`. We also hide this partially applied class by making it package private and placing it inside an object. -### Implicit naming +### Implicit naming In a widely-used library it's important to minimize the chance that the names of implicits will be used by others and therefore name our implicits according to the following rules: @@ -84,5 +84,32 @@ As an example, an implicit instance of `Monoid` for `List` defined in the packag This rule is relatively flexible. Use what you see appropriate. The goal is to maintain uniqueness and avoid conflicts. + + +### Implicit instance priority + +When there are multiple instances provided implicitly, if the type class of them are in the same inheritance hierarchy, +the instances need to be separated out into different abstract class/traits so that they don't conflict with each other. The names of these abstract classes/traits should be numbered with a priority with 0 being the highest priority. The abstract classes/trait +with higher priority inherits from the ones with lower priority. The most specific (whose type class is the lowest in the hierarchy) instance should be placed in the abstract class/ trait with the highest priority. Here is an example. + +```scala +@typeclass +trait Functor[F[_]] + +@typeclass +trait Monad[F[_]] extends Functor + +... +object Kleisli extends KleisliInstance0 + +abstract class KleisliInstance0 extends KleisliInstance1 { + implicit def catsDataMonadForKleisli[F[_], A]: Monad[Kleisli[F, A, ?]] = ... +} + +abstract class KleisliInstance1 { + implicit def catsDataFunctorForKleisli[F[_], A]: Functor[Kleisli[F, A, ?]] = ... +} +``` + #### TODO: Once we drop 2.10 support, AnyVal-extending class constructor parameters can be marked as private.