22

The question says it all, really. I know a (Scala) Monad looks like this:

trait Monad[M[_]] {
  def pure[A](a : A) : M[A]
  def bind[A, B](ma : M[A], f : A => M[B]) : M[B]
}

What does a Monad Transformer look like? And what are they used for?


EDIT. Consider the following REPL session: if a monad transformer somehow decorates a monad with reader capabilities (or vice versa)

Let's say I just want to use replicateM from Scalaz;

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> some(4).replicateM[List](2)
res20: Option[List[Int]] = Some(List(4, 4))

Now let's say, rather than having an Option[Int], I need to read an Int value from a File:

scala> val f = (_ : java.io.File) => some(1)
f: (java.io.File) => Option[Int] = <function1>

So, I can treat this reader, as if it was a Monad?

scala> ReaderT(f).replicateM[List](2)
<console>:16: error: value replicateM is not a member of scalaz.ReaderT[Option,java.io.File,Int]
       ReaderT(f).replicateM[List](2)
                  ^

Err, no.

Apologies if this all seems stupid, I'm just trying to understand what lovely goodness my wrapping the File => Option[Int] in a ReaderT can actually buy me.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449

3 Answers3

8

Monad Transformers are used for combining / extending monads (add capabilities of one monad to another). E.g., ReaderT (Reader Transformer) enriches given monad M with Reader capabilities (transforms given monad into Reader retaining original features of M).

At the same time, Monad Transformers are normal monads that have bind, return, and other operations.

You can find examples of monad transformers in Scalaz - e.g., for Reader and State monads.

Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
  • 2
    Could you give me a pratical example of `ReaderT`? being used to imperative programming, it is *far from easy* looking at a type to figure out how it might be used. Well, it is for me, anyhow. – oxbow_lakes Feb 21 '11 at 16:40
  • 1
    I've amended the question with an example of wrapping a function `File => Option[Int]` in a `ReaderT`. I'm still puzzled as to what I can do with my shiny new `ReaderT` – oxbow_lakes Feb 21 '11 at 18:40
8

Monad transformers are type functions that when applied to a monad type, generate a new monad, that combines the behavior of both components.

E.g. in the xmonad window manager, the computations run inside:

newtype X a = X (ReaderT XConf (StateT XState IO) a)

that is, a Reader composed with a State and an IO monad.

  • Reader gives access to read-only memory
  • State provides a form of read-write state
  • IO allows arbitrary external effects

Note that monad transforms are thus higher-rank types. They take a monadic type of kind (* -> *), and yield a new type of that kind.

As always, the Haskell wiki has some useful content:

Where it all began:

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
1

I don't think Reader is for reading values from a file. Pretty sure it's for reading values of configuration. I think of it as an alternative to global variables, statics, or dynamic/thread-local variables (called "special variables" in Common Lisp or sometimes fluide variables in Scheme with it's "fluid-let"). So, use Reader/ReaderT rather than access a global or dynamic variable and rather than pass parameters into each of your methods that may require access to some configuration option. This can be useful when some very deep piece of code suddenly requires access to a new configuration option. You can pass the option down from your main() function, sneakily access a global or use Reader/ReaderT.

Steven Shaw
  • 6,063
  • 3
  • 33
  • 44
  • According to Scalaz, a `ReaderT` just encapsulates a function `A => M[B]`. Presumably in your case `A` is `MyGlobalParams` whereas in my example, it was a `File`. I still don't get what this actually buys me, though. – oxbow_lakes Feb 23 '11 at 12:26