Skip to content

Instantly share code, notes, and snippets.

@dgouyette
Last active December 16, 2017 12:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgouyette/fcbc58728fd62fc67150c9393dd23b14 to your computer and use it in GitHub Desktop.
Save dgouyette/fcbc58728fd62fc67150c9393dd23b14 to your computer and use it in GitHub Desktop.
trait Functor[Box[_]] {
def map[In, Out](boxA: Box[In])(f: In => Out): Box[Out]
}
object Functor {
implicit val functorOption = new Functor[Option] {
override def map[In, Out](boxA: Option[In])(f: In => Out) = boxA.map(f)
}
implicit val functorList = new Functor[List] {
override def map[A, B](boxA: List[A])(f: A => B) = boxA.map(f)
}
}
trait Semigroupal[Box[_]] {
def product[A, B](fa: Box[A], fb: Box[B]): Box[(A, B)]
}
object Semigroupal {
implicit val semigroupalOption = new Semigroupal[Option] {
override def product[A, B](fa: Option[A], fb: Option[B]) = {
(fa, fb) match {
case (Some(a), Some(b)) => Some(a, b)
case _ => None
}
}
}
implicit val semigroupalList = new Semigroupal[List] {
override def product[A, B](la: List[A], lb: List[B]) : List[(A, B)] = {
for {
a <- la
b <- lb
} yield List((a, b))
}.flatten
}
}
val t1Int: Option[Int] = Some(5)
val t2Int: Option[Int] = Some(6)
val t1List = List(6)
val t2List = List(7)
case class MyTuple2[Box[_], T](a: Box[T], b: Box[T]) {
def mapN(f: (T, T) => T)(implicit functor: Functor[Box], semigroupal: Semigroupal[Box]) = {
functor.map(semigroupal.product(a, b)) { case (t1, t2) => f(t1, t2) }
}
}
object MyTuple2 {
implicit def t2x[Box[_],T](t: (Box[T], Box[T])) = MyTuple2(t._1, t._2)
}
import MyTuple2._
(t1Int, t2Int).mapN(_ + _)
(t1List, t2List).mapN(_ + _)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment