Last active
March 10, 2018 01:46
-
-
Save nbenns/a8450739e6b6fefea43b8408b8c4af6f to your computer and use it in GitHub Desktop.
Free
This file contains 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
import scala.language.higherKinds | |
import cats.Functor | |
import cats.implicits._ | |
/* | |
* A Free Functor is a Functor definition that doesn't care what F[_] is. | |
* We are Free from having to know about F[_] until we run() it. | |
* It uses the second Functor Law: fmap (g . f) = fmap g . fmap f | |
* FreeF is just a container that composes functions | |
* When you run it, you give it an actual container and the intial value | |
*/ | |
case class FreeF[A, B](f: A => B) { | |
def run[F[_]](app: (F[A], A => B) => B)(x: F[A]): B = app(x, f) | |
} | |
object FreeF { | |
def apply[A]: FreeF[A, A] = FreeF(identity[A]) | |
} | |
implicit def freeFunc[T]: Functor[FreeF[T, ?]] = new Functor[FreeF[T, ?]] { | |
override def map[A, B](fa: FreeF[T, A])(f: A => B) = FreeF[T, B](fa.f andThen f) | |
} | |
val effectfulOps: FreeF[Int, String] = | |
FreeF[Int] | |
.map(_ + 1) | |
.map(_.toString + "!") | |
val optionOps: Option[Int] => String = effectfulOps.run[Option]((v, f) => v match { | |
case Some(a) => f(a) | |
case None => "none" | |
}) | |
optionOps(Some(2)) // 3! | |
val eitherOps: Either[String, Int] => String = effectfulOps.run[Either[String, ?]]((v, f) => v match { | |
case Right(a) => f(a) | |
case Left(b) => b | |
}) | |
eitherOps(Right(1)) // 2! | |
// Custom data type - no functor instance is defined for this type | |
sealed trait Custom[+A] | |
case object Nope extends Custom[Nothing] | |
case class Yep[A](a: A) extends Custom[A] | |
val customOps: Custom[Int] => String = effectfulOps.run[Custom]((v, f) => v match { | |
case Yep(a) => f(a) | |
case Nope => "nope" | |
}) | |
customOps(Yep(5)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment