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 | |
| } |
This comment has been minimized.
This comment has been minimized.
|
Thanks Mr Observant! |
This comment has been minimized.
This comment has been minimized.
|
Thanks for the thought provoking talk. Could you take a look at my attempt to use RWST here: https://gist.github.com/2364137 -- specifically, the definition of the log and the invokeService functions? I had to create PointedFunctor in order to implement log generically. Is that the correct approach? |
This comment has been minimized.
This comment has been minimized.
|
On 12/04/12 11:45, Michael Pilquist wrote:
Thanks for the thought provoking talk. Could you take a look at my attempt to use RWST here: https://gist.github.com/2364137 -- specifically, the definition of the log and the invokeService functions? I had to create PointedFunctor in order to implement log generically. Is that the correct approach?
---
Reply to this email directly or view it on GitHub:
https://gist.github.com/2360532
Looks pretty spot-on.
Often, the point operation exists alongside an existing trait, so as to
provide laws. e.g. trait Functor; trait PointedFunctor extends Functor.
There is a solid movement for restructuring the position of the point
operation in class hierarchies, of which I am a part of. Here is a
diagram of it: http://hackage.haskell.org/package/semigroupoids (though
I still have more minor reservations here).
##
Tony Morris
http://tmorris.net/
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
There's a typo on line 109 -- instead of def id[A]: A, it should be def id: A.