Last active
October 16, 2016 11:30
-
-
Save milessabin/c4b7285f40f7a1cc3593d93fa0ad3a02 to your computer and use it in GitHub Desktop.
Intersecting both instances and syntax to resolve ambiguity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo | |
import scala.language.higherKinds | |
import scala.language.implicitConversions | |
trait Functor[F[_]] { | |
def map[A, B](fa: F[A])(f: A => B): F[B] | |
} | |
trait Monad[F[_]] extends Functor[F] { | |
def pure[A](a: A): F[A] | |
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] | |
} | |
trait Traverse[F[_]] extends Functor[F] | |
trait FunctorSyntax[F[_], A] { | |
val fa: F[A] | |
val I: Functor[F] | |
def map[B](f: A => B): F[B] = I.map(fa)(f) | |
} | |
object FunctorSyntax { | |
implicit def functorSyntax[F[_], A](fa0: F[A])(implicit I0: Functor[F]): FunctorSyntax[F, A] = | |
new FunctorSyntax[F, A] { val fa = fa0 ; val I = I0 } | |
} | |
trait MonadSyntax[F[_], A] extends FunctorSyntax[F, A] { | |
val I: Monad[F] | |
def pure[A](a: A): F[A] = I.pure(a) | |
def flatMap[B](f: A => F[B]): F[B] = I.flatMap(fa)(f) | |
} | |
object MonadSyntax { | |
implicit def monadSyntax[F[_], A](fa0: F[A])(implicit I0: Monad[F]): MonadSyntax[F, A] = | |
new MonadSyntax[F, A] { val fa = fa0 ; val I = I0 } | |
} | |
trait TraverseSyntax[F[_], A] extends FunctorSyntax[F, A] { | |
val I: Traverse[F] | |
} | |
object TraverseSyntax { | |
implicit def traverseSyntax[F[_], A](fa0: F[A])(implicit I0: Traverse[F]): TraverseSyntax[F, A] = | |
new TraverseSyntax[F, A] { val fa = fa0 ; val I = I0 } | |
} | |
trait MTSyntax[F[_], A] extends MonadSyntax[F, A] with TraverseSyntax[F, A] { | |
val I: Monad[F] with Traverse[F] | |
} | |
object MTSyntax { | |
implicit def mtSyntax[F[_], A](fa0: F[A])(implicit I0: Monad[F] with Traverse[F]): MTSyntax[F, A] = | |
new MTSyntax[F, A] { val fa = fa0 ; val I = I0 } | |
} | |
object ListInstances { | |
implicit val listInstance: Monad[List] with Traverse[List] = | |
new Monad[List] with Traverse[List] { | |
def pure[A](a: A): List[A] = List(a) | |
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) | |
def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f) | |
} | |
} | |
object Demo { | |
import ListInstances._, FunctorSyntax._, MonadSyntax._, TraverseSyntax._, MTSyntax._ | |
def foo[F[_]](implicit MT: Monad[F] with Traverse[F]): F[Int] = { | |
for { | |
a <- MT.pure(10) | |
b <- MT.pure(20) | |
} yield a+b | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment