Skip to content

Instantly share code, notes, and snippets.

@mpilquist
Created September 8, 2012 21:26
Show Gist options
  • Save mpilquist/3679896 to your computer and use it in GitHub Desktop.
Save mpilquist/3679896 to your computer and use it in GitHub Desktop.
Template approach to avoiding explicit type annotations
import scalaz._
/**
* Provides type aliases and utilities for working with state disjunctions.
*
* A state disjunction is a function `S => F[(S, L \/ R)]` wrapped in the StateT and EitherT monad
* transformers.
*
* See `StateDisjunctionT` and `StateDisjunction` for more information.
*/
trait StateDisjunctions {
/** Function `S => F[(S, L \/ R)]` wrapped in `StateT` and `EitherT`. */
final type StateDisjunctionT[F[+_], S, +L, +R] = EitherT[({type l[+a] = StateT[F, S, a]})#l, L, R]
/** Provides utilities for working with `StateDisjunctionT`. */
object StateDisjunctionT {
/** Constructs a `StateDisjunctionT` given a `StateT[F, S, L \/ R]`. */
def apply[F[+_], S, L, R](st: StateT[F, S, L \/ R]): StateDisjunctionT[F, S, L, R] =
EitherT[({type l[+a] = StateT[F, S, a]})#l, L, R](st)
/** Constructs a `StateDisjunctionT` given an `R`. */
def point[F[+_], S, L, R](r: R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
EitherT.eitherTPointed[({type l[+a] = StateT[F, S, a]})#l, L].point(r)
/** Constructs a `StateDisjunctionT` given an `F[R]`. */
def pointT[F[+_], S, L, R](fr: F[R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
apply(StateT { s => F0.map(fr) { r => (s, \/.right(r)) } })
/** Constructs a `StateDisjunctionT` given a `L \/ R`. */
def liftE[F[+_], S, L, R](e: L \/ R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
apply(StateT.stateTPointed[S, F].point(e))
/** Constructs a `StateDisjunctionT` given a `F[L \/ R]`. */
def liftET[F[+_], S, L, R](e: F[L \/ R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
apply(StateT { s => F0.map(e) { ee => (s, ee) } })
/** Constructs a `StateDisjunctionT` given a `StateT[F, S, R]`. */
def liftS[F[+_], S, L, R](st: StateT[F, S, R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
apply(st map { r => \/.right[L, R](r) })
/** Creates an object that can be used to work with `StateDisjunctionT`s with the fixed type `F`. */
def template[F[+_]] = new StateDisjunctionTemplateF[F] {}
}
trait StateDisjunctionTemplateF[F[+_]] {
final type Type[S, +L, +R] = StateDisjunctionT[F, S, L , R]
final def fixState[S] = new StateDisjunctionTemplateFS[F, S] {}
final def apply[S, L, R](st: StateT[F, S, L \/ R]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT(st)
final def point[S, L, R](r: R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.point(r)
final def pointT[S, L, R](fr: F[R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.pointT(fr)
final def liftE[S, L, R](e: L \/ R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftE(e)
final def liftET[S, L, R](e: F[L \/ R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftET(e)
final def liftS[S, L, R](st: StateT[F, S, R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftS(st)
}
trait StateDisjunctionTemplateFS[F[+_], S] {
final type Type[+L, +R] = StateDisjunctionT[F, S, L, R]
final def fixLeft[L] = new StateDisjunctionTemplateFSL[F, S, L] {}
final def apply[L, R](st: StateT[F, S, L \/ R]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT(st)
final def point[L, R](r: R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.point(r)
final def pointT[L, R](fr: F[R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.pointT(fr)
final def liftE[L, R](e: L \/ R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftE(e)
final def liftET[L, R](e: F[L \/ R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftET(e)
final def liftS[L, R](st: StateT[F, S, R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftS(st)
}
trait StateDisjunctionTemplateFSL[F[+_], S, L] {
final type Type[+R] = StateDisjunctionT[F, S, L, R]
final def apply[R](st: StateT[F, S, L \/ R]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT(st)
final def point[R](r: R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.point(r)
final def pointT[R](fr: F[R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.pointT(fr)
final def liftE[R](e: L \/ R)(implicit F0: Pointed[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftE(e)
final def liftET[R](e: F[L \/ R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftET(e)
final def liftS[R](st: StateT[F, S, R])(implicit F0: Functor[F]): StateDisjunctionT[F, S, L, R] =
StateDisjunctionT.liftS(st)
}
// Needed due to limitation in 2.9 implicit lookup
implicit def stateDisjunctionMonad[F[+_]: Monad, S, L] = EitherT.eitherTMonad[({type l[+a] = StateT[F, S, a]})#l, L](StateT.stateTMonadState[S, F])
final type StateDisjunction[S, +L, +R] = StateDisjunctionT[Id.Id, S, L, R]
final val StateDisjunction = StateDisjunctionT.template[Id.Id]
}
object StateDisjunctions extends StateDisjunctions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment