Skip to content

Instantly share code, notes, and snippets.

@awekuit
Last active August 29, 2015 14:10
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 awekuit/54f554653c53465938c2 to your computer and use it in GitHub Desktop.
Save awekuit/54f554653c53465938c2 to your computer and use it in GitHub Desktop.
型引数の基本から学ぶ、FreeモナドとCoyoneda http://awekuit.hatenablog.com/entry/2014/12/04/091402
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.language.reflectiveCalls
trait Functor[F[_]] {
def map[A, B](m: F[A])(f: A => B): F[B]
}
implicit def functorOps[F[_] : Functor, A](self: F[A]) = new {
def map[B](f: A => B): F[B] = implicitly[Functor[F]].map(self)(f)
}
abstract class HKFold[F[_] : Functor, A] {
def point[B] (x: B): HKFold[F, B] =
F0[F,B](x)
def map[B] (f: A => B): HKFold[F, B] =
flatMap(x => point(f(x)))
def flatMap[B](f: A => HKFold[F, B]): HKFold[F, B]
}
case class F0[F[_] : Functor, A](x: A) extends HKFold[F, A] {
def flatMap[B](f: A => HKFold[F, B]): HKFold[F, B] =
f(x)
}
case class F1[F[_] : Functor, A](x: F[A]) extends HKFold[F, A] {
def flatMap[B](f: A => HKFold[F, B]): HKFold[F, B] = {
val y = x.map(f)
F3[F,B](y)
}
}
case class F3[F[_] : Functor, A](x: F[HKFold[F, A]]) extends HKFold[F, A] {
def flatMap[B](f: A => HKFold[F, B]): HKFold[F, B] = {
val res = x.map{y =>
y.flatMap(z => f(z))
}
F3(res)
}
}
implicit val optionFunctor = new Functor[Option] {
def map[A, B](m: Option[A])(f: A => B): Option[B] = m.map(f)
}
val res = for {
a <- F1(Option(3))
b <- F1(Option(5))
c <- F1(Option(10))
} yield a * b + c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment