Skip to content

Instantly share code, notes, and snippets.

@SegFaultAX
Last active July 20, 2019 00:01
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 SegFaultAX/afa668b2b7c4639d9037b7bd06222d74 to your computer and use it in GitHub Desktop.
Save SegFaultAX/afa668b2b7c4639d9037b7bd06222d74 to your computer and use it in GitHub Desktop.
Basic typeclasses [Scala]
object typeclasses {
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
trait Apply[F[_]] extends Functor[F] {
def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] =
map2(ff, fa)(_(_))
}
trait Applicative[F[_]] extends Apply[F] {
def pure[A](a: A): F[A]
}
trait Bind[F[_]] extends Apply[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
override def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
flatMap(fa)(a => map(fb)(b => f(a, b)))
}
trait Monad[F[_]] extends Bind[F] with Applicative[F] {
override def map[A, B](fa: F[A])(f: A => B): F[B] =
flatMap(fa)(a => pure(f(a)))
}
trait MonadOps[F[_], A] {
def map[B](f: A => B): F[B]
def flatMap[B](f: A => F[B]): F[B]
}
implicit def monadSyntax[F[_], A](fa: F[A])(implicit ev: Monad[F]): MonadOps[F, A] = new MonadOps[F, A] {
override def map[B](f: A => B): F[B] = ev.map(fa)(f)
override def flatMap[B](f: A => F[B]): F[B] = ev.flatMap(fa)(f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment