Skip to content

Instantly share code, notes, and snippets.

@tonymorris
Created April 11, 2012 16:59
Show Gist options
  • Select an option

  • Save tonymorris/2360532 to your computer and use it in GitHub Desktop.

Select an option

Save tonymorris/2360532 to your computer and use it in GitHub Desktop.
Reader/Writer/State transformer in Scala
case class ReaderWriterStateT[R, W, S, F[_], A](
run: (R, S) => F[(W, A, S)]
) {
def map[B](f: A => B)(implicit F: Functor[F])
: ReaderWriterStateT[R, W, S, F, B] =
ReaderWriterStateT {
case (r, s) => F.map(run(r, s)) {
case (w, a, s) => (w, f(a), s)
}
}
def flatMap[B](f: A => ReaderWriterStateT[R, W, S, F, B])
(implicit F: FlatMap[F], W: Semigroup[W])
: ReaderWriterStateT[R, W, S, F, B] =
ReaderWriterStateT {
case (r, s) => F.flatMap(run(r, s)) {
case (w1, a, s1) => F.map(f(a) run (r, s1)) {
case (w2, b, s2) => (W.op(w1, w2), b, s2)
}
}
}
}
object ReaderWriterStateT {
type ReaderWriterState[R, W, S, A] =
ReaderWriterStateT[R, W, S, Id, A]
}
case class ReaderT[A, F[_], B](
rd: A => F[B]
) {
def rws[W, S](implicit F: Functor[F], W: Monoid[W])
: ReaderWriterStateT[A, W, S, F, B] =
ReaderWriterStateT {
case (r, s) => F.map(rd(r))(
(W.id, _, s)
)
}
}
object ReaderT {
type Reader[A, B] =
ReaderT[A, Id, B]
}
case class WriterT[W, F[_], A](
wx: F[(W, A)]
) {
def rws[R, S](implicit F: Functor[F])
: ReaderWriterStateT[R, W, S, F, A] =
ReaderWriterStateT {
case (r, s) => F.map(wx){
case (w, a) => (w, a, s)
}
}
}
object WriterT {
type Writer[W, A] =
WriterT[W, Id, A]
}
case class StateT[S, F[_], A](
st: S => F[(A, S)]
) {
def rws[W, R](implicit F: Functor[F], W: Monoid[W])
: ReaderWriterStateT[R, W, S, F, A] =
ReaderWriterStateT {
case (r, s) => F.map(st(s)){
case (a, s) => (W.id, a, s)
}
}
}
object StateT {
type State[S, A] =
StateT[S, Id, A]
}
case class Id[A](a: A)
object Id {
implicit val IdFlatMap: FlatMap[Id] =
new FlatMap[Id] {
def fmap[A, B](f: A => B) =
i => Id(f(i.a))
def bind[A, B](f: A => Id[B]) =
i => f(i.a)
}
}
trait Functor[F[_]] {
def fmap[A, B](f: A => B): F[A] => F[B]
def map[A, B](a: F[A])(f: A => B): F[B] =
fmap(f)(a)
}
trait FlatMap[F[_]] extends Functor[F] {
def bind[A, B](f: A => F[B]): F[A] => F[B]
def flatMap[A, B](a: F[A])(f: A => F[B]): F[B] =
bind(f)(a)
}
trait Semigroup[A] {
def op(a1: A, a2: A): A
}
trait Monoid[A] extends Semigroup[A] {
def id: A
}
@tonymorris
Copy link
Copy Markdown
Author

tonymorris commented Apr 12, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment