Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.