
*Question 1: Are monad stacks "transparent" -- that is, can one use a layer in the middle of a monad stack without thinking about other layers?* In learning about how to stack multiple monads (or more literally, how to stack monad transformers on top of a monad), I was expecting that in order to reach into the middle of the stack, one would have to stay aware of the order in which the stack was created, and unwrap outer transformers to get there. That appears to be false. For instance, the program UglyStack.hs in Chapter 18 (Monad Transformers) of Real World Haskell http://book.realworldhaskell.org/read/monad-transformers.html includes a function called "constrainedCount" that, in a ReaderT (StateT IO) stack, calls "ask", "get" and some IO functions as if no layer of the stack interferes with any of the others. Is that true in general? That is, if I build on top of a monad M a stack of monad transformers T1 T2 T3 ... TN M, and each of the Tn have different functions associated with them, call I call those functions without even remembering the order in which the transformers were stacked? Does the order of the stack constrain the programmer in how they chain execution functions like runReader, but not otherwise? *Question 2: Does a monad's scope extend maximally upward through the call stack?* All the programs I have seen that use monads keep them at the top scope: The "main" function will use them, and perhaps functions it calls, but if one descends low enough into the call stack, one escapes from the monad context into pure functional code. Can one ever escape a monad in the reverse direction? Stated differently: Monadic code can call pure code. Can pure code ever call monadic code?

On Mon, Nov 3, 2014 at 10:02 PM, Jeffrey Brown
*Question 1: Are monad stacks "transparent" -- that is, can one use a layer in the middle of a monad stack without thinking about other layers?*
In learning about how to stack multiple monads (or more literally, how to stack monad transformers on top of a monad), I was expecting that in order to reach into the middle of the stack, one would have to stay aware of the order in which the stack was created, and unwrap outer transformers to get there.
If you're doing it manually, yes, that would be true. Newtype deriving can be used to hide it, assuming that the levels are distinct enough: you can't easily pick between two MonadReader-s, for example, without lifting past one of them (and therefore having to at least know what order they are in). Is that true in general? That is, if I build on top of a monad M a stack of
monad transformers T1 T2 T3 ... TN M, and each of the Tn have different functions associated with them, call I call those functions without even remembering the order in which the transformers were stacked? Does the order of the stack constrain the programmer in how they chain execution functions like runReader, but not otherwise?
If you use newtype deriving, you can mostly avoid depth or ordering. One remaining sticky case is that of `fail`; if a monad in the middle calls `fail`, state below that monad *may* be lost. (But `fail` is rather badly behaved in general, and is best avoided.) Stated differently: Monadic code can call pure code. Can pure code ever
call monadic code?
Something like runReaderT or runST? Or in the extreme case, unsafePerformIO --- which is unsafe for a reason, and trying to use it to sneak into IO from pure code will usually cause major problems, because pure code does not expect non-deterministic results. Otherwise, the type system does its best to avoid you unexpectedly dipping into e.g. IO from inside pure code. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

On Mon, Nov 3, 2014 at 10:02 PM, Jeffrey Brown
wrote: Stated differently: Monadic code can call pure code. Can pure code ever call monadic code? Something like runReaderT or runST? Or in the extreme case, unsafePerformIO --- which is unsafe for a reason, and trying to use it to sneak into IO from pure code will usually cause major problems, because
On Nov 3, 2014 9:15 PM, "Brandon Allbery"

On 11/04/2014 03:02 AM, Jeffrey Brown wrote:
*Question 1: Are monad stacks "transparent" -- that is, can one use a layer in the middle of a monad stack without thinking about other layers?*
In learning about how to stack multiple monads (or more literally, how to stack monad transformers on top of a monad), I was expecting that in order to reach into the middle of the stack, one would have to stay aware of the order in which the stack was created, and unwrap outer transformers to get there.
That appears to be false. For instance, the program UglyStack.hs in Chapter 18 (Monad Transformers) of Real World Haskell http://book.realworldhaskell.org/read/monad-transformers.html includes a function called "constrainedCount" that, in a ReaderT (StateT IO) stack, calls "ask", "get" and some IO functions as if no layer of the stack interferes with any of the others.
Each of these functions works thanks to typeclasses: someone made the Monad in question an instance of all those typeclasses so that you could use these functions as if they were all on the same layer. In reality the lifting is done at instance declarations.
Is that true in general? That is, if I build on top of a monad M a stack of monad transformers T1 T2 T3 ... TN M, and each of the Tn have different functions associated with them, call I call those functions without even remembering the order in which the transformers were stacked? Does the order of the stack constrain the programmer in how they chain execution functions like runReader, but not otherwise?
It definitely matters how you stack your transformer especially when it comes to unwrapping it: did you want a ‘Maybe (IO a)’ or ‘IO (Maybe a)’? This is a bit of a silly example but hopefully you get the idea that the ordering can't be randomly scrambled around without thought.
*Question 2: Does a monad's scope extend maximally upward through the call stack?*
All the programs I have seen that use monads keep them at the top scope: The "main" function will use them, and perhaps functions it calls, but if one descends low enough into the call stack, one escapes from the monad context into pure functional code. Can one ever escape a monad in the reverse direction?
Stated differently: Monadic code can call pure code. Can pure code ever call monadic code?
This whole question just doesn't make sense to me at all. First of all, monadic code (whatever that is meant to mean) is pure. From this alone the question is meaningless. If I wrap something in Identity is it now not pure somehow? Did you know that ((->) a) also forms a Monad? Are functions now not pure code? There is no difference between ‘monadic code’ and ‘pure code’, they are the same thing, it's just that the former is dressed up into a form that's convenient to work with. So you'll have to give a clearer definition of ‘pure’ and ‘monadic’ code here and show that they are somehow distinct in order to even have hope to asking such a thing. I suspect you can not ;). -- Mateusz K.
participants (4)
-
Brandon Allbery
-
Jeffrey Brown
-
Mateusz Kowalczyk
-
Mike Meyer