In the cats library we have in the package cats.instances
in function.class
trait FunctionInstances extends cats.kernel.instances.FunctionInstances with Function0Instances with Function1Instances
....
....
....
sealed private[instances] trait Function1Instances extends Function1Instances0 {
implicit def catsStdContravariantMonoidalForFunction1[R: Monoid]: ContravariantMonoidal[* => R] =
new ContravariantMonoidal[* => R] {
def unit: Unit => R = Function.const(Monoid[R].empty)
def contramap[A, B](fa: A => R)(f: B => A): B => R =
fa.compose(f)
def product[A, B](fa: A => R, fb: B => R): ((A, B)) => R = {
case (a, b) => Monoid[R].combine(fa(a), fb(b))
}
}
implicit def catsStdMonadForFunction1[T1]: Monad[T1 => *] =
new Monad[T1 => *] {
def pure[R](r: R): T1 => R = _ => r
def flatMap[R1, R2](fa: T1 => R1)(f: R1 => T1 => R2): T1 => R2 =
t => f(fa(t))(t)
override def map[R1, R2](fa: T1 => R1)(f: R1 => R2): T1 => R2 =
f.compose(fa)
and we can see
sealed private[instances] trait Function1Instances
which makes its member only visible in the package Instance
In the Package Object Instances in the package cats, we have:
package object instances {
.......
.......
object function extends FunctionInstances with FunctionInstancesBinCompat0
.......
}
Then in the Invariant.class in cats package, we have:
object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantInstances0 {
....
....
implicit def catsMonadForFunction1[I]: Monad[I => *] = cats.instances.function.catsStdMonadForFunction1[I]
....
I wonder how catsStdMonadForFunction1[I]
is visible to Invariant. I thought could only be visble from package instances including the associated package object instances.
So the object function
can see and call catsStdMonadForFunction1[I]
because it implements the trait and the visibility is scope to package instances . But for I don't understand why Invariant
can see that method.
Can someone explain that visbility rule applied here ?