Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Scalaz `F[_] : Applicative` type constraint imply use of implicit parameters?

I am struggling to understand the following function definition in Traverse trait in Scalaz:

def traverse[F[_] : Applicative, A, B](f: A => F[B], t: T[A]): F[T[B]]

The part I don't understand is F[_] : Applicative.

Now, let's see what Applicative is:

trait Applicative[Z[_]] extends Pointed[Z] with Apply[Z] {
  override def fmap[A, B](fa: Z[A], f: A => B): Z[B] = this(pure(f), fa)
  override def apply[A, B](f: Z[A => B], a: Z[A]): Z[B] = liftA2(f, a, (_:A => B)(_: A))
  def liftA2[A, B, C](a: Z[A], b: Z[B], f: (A, B) => C): Z[C] = apply(fmap(a, f.curried), b)
}

Here, for traverse to work for some type F, one needs to bring an implicit object of type Applicative[F] in scope.

I'd like to understand several things:

  1. Wat exactly does F[_] : Applicative mean?
  2. Why does F[_] has something to do with Applicative? We need Applicative[F], not F[something] extends Applicative right?
  3. Why does this method use implicit values of type Applicative[F] without declaring implicit parameters?
like image 264
Rotsor Avatar asked Aug 18 '11 14:08

Rotsor


1 Answers

I think all three questions can be answered with the fact that this notation:

def traverse[F[_] : Applicative, A, B](f: A => F[B], t: T[A]): F[T[B]]

is equivalent to this:

def traverse[F[_], A, B](f: A => F[B], t: T[A])(implicit $ev: Applicative[F]): F[T[B]]

The first notation is known as a context bound for F[_].

like image 66
Jean-Philippe Pellet Avatar answered Oct 17 '22 22:10

Jean-Philippe Pellet