Skip to content

Instantly share code, notes, and snippets.

@blast-hardcheese
Created April 19, 2016 03:30
Show Gist options
  • Save blast-hardcheese/eab0b0423977f7d84ba103518e161974 to your computer and use it in GitHub Desktop.
Save blast-hardcheese/eab0b0423977f7d84ba103518e161974 to your computer and use it in GitHub Desktop.
package se.hardchee.Pickr
import scala.language.higherKinds
import scala.language.implicitConversions
import scalaz._
import scalaz.std.function._
import scalaz.syntax.monad._
import se.hardchee.Pickr.algebras._
object Main extends App {
sealed trait Auth[T]
case object IsLoggedIn extends Auth[Boolean]
case object LogIn extends Auth[Unit]
case object LogOut extends Auth[Unit]
sealed trait TodoModel[T]
case object GetItem extends TodoModel[String]
type AuthStore[A] = State[Boolean, A]
object AuthInterpreter extends (Auth ~> AuthStore) {
def apply[T](fa: Auth[T]) = {
fa match {
case IsLoggedIn => State { s => (s, s) }
case LogIn => State { s => (true, ()) }
case LogOut => State { s => (false, ()) }
}
}
}
object TodoModelInterpreter extends (TodoModel ~> AuthStore) {
def apply[T](fa: TodoModel[T]) = {
fa match {
case GetItem => State { s => (s, "Super secret string!") }
}
}
}
def prog[F[_]](implicit A: Inject[Auth, F], T: Inject[TodoModel, F]): Free.FreeC[F, String] = {
for {
loggedIn <- IsLoggedIn
item <- if (loggedIn) GetItem.liftI else LogOut.liftI
} yield item
}
type PROG[A] = Coproduct[Auth, TodoModel, A]
val interpreter: PROG ~> AuthStore = AuthInterpreter or TodoModelInterpreter
prog[PROG].foldMap(Coyoneda.liftTF(interpreter))
}
package se.hardchee.Pickr
import scala.language.higherKinds
import scala.language.implicitConversions
import scalaz.{ Coproduct, Free, Inject, ~>, \/-, -\/ }
package object algebras {
implicit def liftFCInj[A, P[_], F[_]](x: P[A])(implicit I: Inject[P, F]): Free.FreeC[F, A] = {
Free.liftFC(I.inj(x))
}
implicit class RichFreeC[P[_], A](x: P[A]) {
def liftI[F[_]](implicit I: Inject[P, F]): Free.FreeC[F, A] = liftFCInj(x)
}
// enhancing natural transformations with an or operator
implicit class NaturalTransformationOrOps[F[_], H[_]](private val f2h: F ~> H) extends AnyVal {
type Copro[F[_], G[_]] = { type f[x] = Coproduct[F, G, x] } // just for better readability
// given F ~> H and G ~> H we derive Copro[F, G]#f ~> H
def or[G[_]](g2h: G ~> H): Copro[F, G]#f ~> H =
new (Copro[F, G]#f ~> H) {
def apply[A](c: Coproduct[F, G, A]): H[A] = c.run match {
case -\/(fa) => f2h(fa)
case \/-(ga) => g2h(ga)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment