Newer
Older
package applicative
import scala.language.higherKinds
trait Applicative[F[_]] {
def unit[A](a: A): F[A]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = map2(ff, fa)((f, a) => f(a))
// implement map using unit and ap, but not flatMap/flatten
def map[A, B](fa: F[A])(f: A => B): F[B] = ???
// implement map2 using unit and ap
// hint: f.curried converts `(A,B) => C` to `A => (B => C)`
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ???
// implement unit first
// then write the signature for ap and map2
// then implement one of them
def compose[G[_]](implicit G: Applicative[G]): Applicative[Lambda[a => F[G[a]]]] = {
val F = this
new Applicative[Lambda[a => F[G[a]]]] {
def unit[A](a: A): F[G[A]] = ???
//note: when you are done implementing this, the test for ap/map2 will result in a StackOverflow until you implement one of them
// override def ap... = ???
// or
// override def map2... = ???
}
}
}