Skip to content

Instantly share code, notes, and snippets.

@AnirudhVyas
Last active March 15, 2020 06:17
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 AnirudhVyas/5e1bad627a40d813edd95e8be1927bb6 to your computer and use it in GitHub Desktop.
Save AnirudhVyas/5e1bad627a40d813edd95e8be1927bb6 to your computer and use it in GitHub Desktop.
Some Basic typeclasses
import scala.language.higherKinds
object TypeClasses {
// applies to type constructors (F[_])
trait Functor[F[_]] {
def map[A, B](xs: F[A])(f: A => B): F[B]
}
implicit object ListFunctor extends Functor[List] {
override def map[A, B](xs: List[A])(f: A => B): List[B] = xs.map(f)
}
implicit object OptionFunctor extends Functor[Option] {
override def map[A, B](xs: Option[A])(f: A => B): Option[B] = xs.map(f)
}
trait ApplicativeFunctor[F[_]] extends Functor[F] {
def pure[A](a: A): F[A]
def zip[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
implicit object ListApplicativeFunctor extends ApplicativeFunctor[List] {
override def pure[A](a: A): List[A] = List(a)
override def zip[A, B](fa: List[A], fb: List[B]): List[(A, B)] = fa.zip(fb)
override def map[A, B](xs: List[A])(f: A => B): List[B] = xs.map(f)
}
implicit object OptionApplicativeFunctor extends ApplicativeFunctor[Option] {
override def pure[A](a: A): Option[A] = Option(a)
override def zip[A, B](fa: Option[A], fb: Option[B]): Option[(A, B)] = (fa, fb) match {
case (Some(a), Some(b)) => Option((a, b))
case (None, _) => None
case (_, None) => None
}
override def map[A, B](xs: Option[A])(f: A => B): Option[B] = xs.map(f)
}
val xOpt = Option.empty[String]
val yOpt = Option.empty[Int]
def zipV(x: Option[String], y: Option[Int]): Option[(String, Int)] = {
implicitly[ApplicativeFunctor[Option]].zip(x, y)
}
trait Monad[F[_]] extends ApplicativeFunctor[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment