Created
October 11, 2011 23:46
-
-
Save lamdor/1279817 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Functor[F[_]] { | |
def fmap[A,B](f: A => B): F[A] => F[B] | |
} | |
sealed trait Fruit | |
class Apple extends Fruit | |
class Orange extends Fruit | |
case class Basket[T](items: T*) | |
object BasketFunctor extends Functor[Basket] { | |
def fmap[T, B](f: T => B) = | |
(b: Basket[T]) => Basket(b.items.map(f): _*) | |
} | |
val apple = new Apple | |
val orange = new Orange | |
val basketOfApples = Basket(List(apple, apple)) | |
val convertToOranges = BasketFunctor.fmap((a: Apple) => orange) | |
trait Pointed[F[_]] { | |
def point[A](a: => A): F[A] | |
} | |
object PointedBasket extends Pointed[Basket] { | |
def point[T](item: => T) = Basket(item) | |
} | |
val oneAppleInABasket = PointedBasket.point(apple) | |
trait PointedFunctor[F[_]] extends Functor[F] with Pointed[F] { | |
val functor: Functor[F] | |
val pointed: Pointed[F] | |
def point[A](a: => A): F[A] = pointed.point(a) | |
def fmap[A,B](f: A => B): F[A] => F[B] = functor.fmap(f) | |
} | |
object BasketPointedFunctor extends PointedFunctor[Basket] { | |
val functor = BasketFunctor | |
val pointed = PointedBasket | |
} | |
trait Applic[F[_]] { | |
def applic[A,B](f: F[A => B]): F[A] => F[B] | |
} | |
object BasketApplic extends Applic[Basket] { | |
def applic[A,B](f: Basket[A => B]) = { (b: Basket[A]) => | |
val product: Seq[B] = b.items.flatMap(i => f.items.map(bf => bf(i))) | |
Basket(product: _*) | |
} | |
} | |
sealed trait Juice[F <: Fruit] | |
case class OrangeJuice extends Juice[Orange] | |
case class AppleJuice extends Juice[Apple] | |
val juicer = (f: Fruit) => f match { | |
case o: Orange => new OrangeJuice | |
case a: Apple => new AppleJuice | |
} | |
val xmasPresent = Basket(juicer, juicer) | |
val basketOfFruit: Basket[Fruit] = Basket(orange, apple, orange) | |
val juiceLikeJackLaLane = BasketApplic.applic(xmasPresent) | |
juiceLikeJackLaLane(basketOfFruit) | |
trait Applicative[F[_]] { | |
val pointedFunctor: PointedFunctor[F] | |
val applic: Applic[F] | |
def functor: Functor[F] = new Functor[F] { | |
def fmap[A, B](f: A => B) = pointedFunctor fmap f | |
} | |
def pointed: Pointed[F] = new Pointed[F] { | |
def point[A](a: => A) = pointedFunctor point a | |
} | |
def fmap[A, B](f: A => B): F[A] => F[B] = functor.fmap(f) | |
def point[A](a: => A): F[A] = pointed.point(a) | |
def apply[A, B](f: F[A => B]): F[A] => F[B] = applic.applic(f) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment