Created
September 8, 2012 21:26
-
-
Save mpilquist/3679896 to your computer and use it in GitHub Desktop.
Template approach to avoiding explicit type annotations
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 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