Skip to content

Instantly share code, notes, and snippets.

@milessabin
Last active October 16, 2016 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milessabin/c4b7285f40f7a1cc3593d93fa0ad3a02 to your computer and use it in GitHub Desktop.
Save milessabin/c4b7285f40f7a1cc3593d93fa0ad3a02 to your computer and use it in GitHub Desktop.
Intersecting both instances and syntax to resolve ambiguity
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