
hello, i was wondering what people think about the following two issues with the monad library: 1. there are the map* functions for different transformers (mapReader, mapWriter, etc.). does anyone use them for anything? while there is something common between them, i am not quite sure exactly what it is. if anyone is using them i would be interested if the same can be achieved by just using the "standard" functionality for the appropriate transformer. i am inclined to remove them from the library, if there are no objections. 2. currently the monad library is under Unstable.Control.Monad, and i would like to move it to some other place, so that we can use it, without the need to later rename everything. the core of it should be more or less stable. since moving libraries at the moment is quite work intensive, it would be nice if we agreed on where to put it, so that we don't have to move it again. i propose that we put all the monads under Monad, thus one would import Monad.State, Monad.ReaderT, or Monad.Transformers. in this way the old monad library can stay under Control.Monad and programs that are using it need not change. at some point in the future we can decide to remove the old library or it can just stay there. and i like the shorter names (not to mention that it is not clear what some of the monads have to do with control). any comments? iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

G'day all. On Fri, Jul 25, 2003 at 12:40:22AM +0200, Iavor Diatchki wrote:
1. there are the map* functions for different transformers (mapReader, mapWriter, etc.). does anyone use them for anything? while there is something common between them, i am not quite sure exactly what it is.
I've used them once, and that was to swap the underlying monad of a transformer. It's occasionally handy, for example, when you want your state to be backtrackable for a small part of your code, to stick a backtracking monad _under_ the top monad transformer. I don't think that you can duplicate this behaviour using the other operations on the monad. A simple solution would be to introduce this typeclass: class (MonadTrans t) => MonadMapTrans t where mapTrans :: (m a -> n b) -> (t m a -> t n b) I'm not happy with the names, but I'm sure someone can think of something better. It might even make sense as a method of MonadTrans itself. Cheers, Andrew Bromage

hello, Andrew J Bromage wrote:
1. there are the map* functions for different transformers (mapReader, mapWriter, etc.). does anyone use them for anything? while there is something common between them, i am not quite sure exactly what it is.
I've used them once, and that was to swap the underlying monad of a transformer. It's occasionally handy, for example, when you want your state to be backtrackable for a small part of your code, to stick a backtracking monad _under_ the top monad transformer.
I don't think that you can duplicate this behaviour using the other operations on the monad.
A simple solution would be to introduce this typeclass:
class (MonadTrans t) => MonadMapTrans t where mapTrans :: (m a -> n b) -> (t m a -> t n b)
i think this type doesn't quite work as often the underlying computation returns a more complicated type (e.g. the state monad also returns a new state). in my other library i had a similar operation, corresponding to the fact that most monad transformers are functors on the category of monads. it works for all transformers except for continuations: class MondaTrans t => MapTrans t where mapTrans :: (Monad m, Monad n) => (forall a. m a -> n a) -> t m b -> t n b intuitively the "forall" constraint says that we are changing just the monad, and not touching the value. to get continuations to work, one needs a map (n a -> m a) as well, i think. any comments about that class? bye iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

G'day all. On Sun, Jul 27, 2003 at 09:28:57PM +0200, Iavor Diatchki wrote:
in my other library i had a similar operation, corresponding to the fact that most monad transformers are functors on the category of monads. it works for all transformers except for continuations:
class MondaTrans t => MapTrans t where mapTrans :: (Monad m, Monad n) => (forall a. m a -> n a) -> t m b -> t n b
intuitively the "forall" constraint says that we are changing just the monad, and not touching the value. to get continuations to work, one needs a map (n a -> m a) as well, i think. any comments about that class?
Looks pretty good to me, though I still don't like the name. Cheers, Andrew Bromage

hello, Andrew J Bromage wrote:
G'day all.
On Sun, Jul 27, 2003 at 09:28:57PM +0200, Iavor Diatchki wrote:
in my other library i had a similar operation, corresponding to the fact that most monad transformers are functors on the category of monads. it works for all transformers except for continuations:
class MondaTrans t => MapTrans t where mapTrans :: (Monad m, Monad n) => (forall a. m a -> n a) -> t m b -> t n b
intuitively the "forall" constraint says that we are changing just the monad, and not touching the value. to get continuations to work, one needs a map (n a -> m a) as well, i think. any comments about that class?
Looks pretty good to me, though I still don't like the name. we could change it but to what?
bye iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

On Fri, Jul 25, 2003 at 12:40:22AM +0200, Iavor Diatchki wrote:
2. currently the monad library is under Unstable.Control.Monad, and i would like to move it to some other place, so that we can use it, without the need to later rename everything. the core of it should be more or less stable. since moving libraries at the moment is quite work intensive, it would be nice if we agreed on where to put it, so that we don't have to move it again. i propose that we put all the monads under Monad, thus one would import Monad.State, Monad.ReaderT, or Monad.Transformers. in this way the old monad library can stay under Control.Monad and programs that are using it need not change. at some point in the future we can decide to remove the old library or it can just stay there. and i like the shorter names (not to mention that it is not clear what some of the monads have to do with control).
You're asking for a new top-level name Monad. My implession from SimonM's library document is that the intention is that top-level names are to be limited (and certainly only added by agreement). In this particular case monads don't seem broad enough to be a category of their own, and they are a sort of control structure. Hierarchical libraries mean changing our expectations about module name length (e.g. Graphics.Rendering.OpenGL.GLU.Tessellation and the like). Lucky Haskell has import aliases. BTW, I've been assembling a small arrow transformer library, and many of the structuring issues are similar. One issue is how fine grained the modules should be. You have a module (Unstable.)Control.Monad.Trans containing transformer classes and also several monad classes. Those monad classes don't necessarily belong in the transformer module; you could even have one module for each. With the monolithic module, users are more likely to need explicit import clauses. Another issue: typically one works with a stack of transformers sitting on a base monad. You have functions for adding or removing a transformer from the top of the stack, and for manipulating the base monad. It might also be useful to have something to remove a State transformer from anywhere in the stack, etc.

You're asking for a new top-level name Monad. My implession from SimonM's library document is that the intention is that top-level names are to be limited (and certainly only added by agreement). In this particular case monads don't seem broad enough to be a category of their own, and they are a sort of control structure. Hierarchical libraries mean changing our expectations about module name length (e.g. Graphics.Rendering.OpenGL.GLU.Tessellation and the like). Lucky Haskell has import aliases. i am not sure what should we put unedr Monad.* if not the monad library. my preference is to use the hirarchical module system to avoid name clashes rather than for classification purposes. and i don't think any hirarchy much deeper than about 4 would be practical, even with aliases. long names are good from software engineering perspective, but only up to a point. this is why i think it is appropriate for the monad library to be in Monad.*. as simon pj pointed out in a talk he gave, it was
BTW, I've been assembling a small arrow transformer library, and many of the structuring issues are similar. One issue is how fine grained the modules should be. You have a module (Unstable.)Control.Monad.Trans containing transformer classes and also several monad classes. Those monad classes don't necessarily belong in the transformer module; you could even have one module for each. With the monolithic module, users are more likely to need explicit import clauses. yes, i agree that this is a tricky one. the choices i made were either
hello, Ross Paterson wrote: probably a mistake to choose such a wierd name for the concept, but hey now we at least won't have name clashes :-) based on what was already in the library, or what i thought would be the most common usage pattern. i am inclined to try an minimize the number of imports as long as that does not lead to too much name pollution. i've had discussions with people who even prefer having _all_ transformers in a single file, so that you can simply import Monad.Transformers and be done with it. to accomodate such users i added the Transformers file that imports all transformers.
Another issue: typically one works with a stack of transformers sitting on a base monad. You have functions for adding or removing a transformer from the top of the stack, and for manipulating the base monad. It might also be useful to have something to remove a State transformer from anywhere in the stack, etc. i've tried to do things like that, but i can't figure out a way to achieve them. what would be the type of such a function? something like:
runInnerState :: (Monad n, MonadState s m) => s -> m a -> n a (and n is the same as m,but without the state component). thanks for the comments iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

Iavor Diatchki wrote:
[...] my preference is to use the hirarchical module system to avoid name clashes rather than for classification purposes.
I think the whole point of the word "hierarchical" *is* classification. Otherwise we shouldn't use an ordered sequence of simple names for naming a module, but a set of names. Furthermore, for a larger API "collector modules" which simply group together related "sub-modules" (see Foreign, Control.Concurrent, ...) are very useful and a very natural place for an introductory documentation. Again a kind of classification...
and i don't think any hirarchy much deeper than about 4 would be practical, even with aliases.
From a user perspective, yes. But deeper hierarchies are sometimes useful for the implementation of larger APIs. And people in biology are quite happy with a *much* deeper hierarchy: :-) http://library.thinkquest.org/11771/english/hi/biology/taxonomy.shtml http://de.wikipedia.org/wiki/Systematik_(Biologie)
long names are good from software engineering perspective, but only up to a point. this is why i think it is appropriate for the monad library to be in Monad.*. [...]
Well, I don't think that additionally typing "Control." will kill anybody... :-) Even if that was the case: There are still the possibilities of aliases and home-grown modules with short names, which simply re-export other modules. Cheers, S.

G'day all. On Tue, Jul 29, 2003 at 11:34:09PM +0200, Sven Panne wrote:
From a user perspective, yes. But deeper hierarchies are sometimes useful for the implementation of larger APIs. And people in biology are quite happy with a *much* deeper hierarchy: :-)
At the moment, a tree-shaped hierarchy works fine for biology. When genetic engineering gets to the point where you can cross a kangaroo with a dragonfly, then the situation will be more analogous to what we face in software engineering. Our taxonomies are, for better or worse, DAG-shaped. SSL, for example, can legitimately go under both "network communication" and "cryptography", which are quite different fields of computer science. Cheers, Andrew Bromage

ons 2003-07-30 klockan 04.26 skrev Andrew J Bromage:
Our taxonomies are, for better or worse, DAG-shaped. SSL, for example, can legitimately go under both "network communication" and "cryptography", which are quite different fields of computer science.
For the record, I don't agree with this. I could agree to having SSL under some sort of "security" category, but it's completely orthogonal to cryptography. I frequently use SSL without encryption because I just need authentication. /Martin -- Martin Sjögren martin@strakt.com Phone: +46 (0)31 7490880 Cell: +46 (0)739 169191 GPG key: http://www.strakt.com/~martin/gpg.html

Andrew J Bromage wrote:
[...] Our taxonomies are, for better or worse, DAG-shaped. SSL, for example, can legitimately go under both "network communication" and "cryptography", which are quite different fields of computer science.
OK, I agree to our DAG argument, but the important part is the "A": We can e.g. put the SSL implementation under Network.SSL and have module Crypto.SSL ( module Network.SSL ) where import Network.SSL for a convenient/consistent taxonomy. (No Jihad about SSL <-> Crypto, please, it is just an example...) Cheers, S.

On Mon, Jul 28, 2003 at 10:51:47PM +0200, Iavor Diatchki wrote:
Another issue: typically one works with a stack of transformers sitting on a base monad. You have functions for adding or removing a transformer from the top of the stack, and for manipulating the base monad. It might also be useful to have something to remove a State transformer from anywhere in the stack, etc. i've tried to do things like that, but i can't figure out a way to achieve them. what would be the type of such a function?
class (MonadState s m, Monad m') => MonadWithState s m m' | m -> m' where liftState :: m' a -> m a runState :: s -> m a -> m' (a,s) instance Monad m => MonadWithState s (StateT s m) m instance MonadWithState s m m' => MonadWithState s (ErrorT e m) (ErrorT e m') ... and similarly for the rest. (Instances that use the same type constructor twice are an embarrassment for Haddock, though.)

Ross Paterson
On Fri, Jul 25, 2003 at 12:40:22AM +0200, Iavor Diatchki wrote:
2. currently the monad library is under Unstable.Control.Monad, and i would like to move it to some other place, so that we can use it, without the need to later rename everything. the core of it should be more or less stable. since moving libraries at the moment is quite work intensive, it would be nice if we agreed on where to put it, so that we don't have to move it again. i propose that we put all the monads under Monad,
You're asking for a new top-level name Monad. My implession from SimonM's library document is that the intention is that top-level names are to be limited (and certainly only added by agreement).
I too would be very reluctant to allocate new top-level names. Monads already have a place in the hierarchy, so the question here is really about the process for deprecating one existing API and replacing it with a new API. I don't have a solution to this issue. However, it is clear that allocating a new namespace every time an API is improved, is a recipe for confusion amongst users when they search for "the" API without a knowledge of the social history. Iavor wants to move the library now, so that people don't have to rename their imports later. But the implication is that the library is still rather experimental, still a little unstable, and what you really want is to encourage more users to actually try it and report on their experience. So my conclusion is that the API is still likely to change anyhow, and so changing the import location later is only a very minor extra hardship. I would say let people use it first, gain more experience with it, refine the API further, and only once it has achieved stability (by the consensus of the community that uses it) should it move into the "main" hierarchy to replace the existing Control.Monad. (At that point, maybe the existing Control.Monad hierarchy should become Control.Monad.Old, with the understanding that it will disappear altogether at a later date?) Regards, Malcolm
participants (6)
-
Andrew J Bromage
-
Iavor Diatchki
-
Malcolm Wallace
-
Martin Sjögren
-
Ross Paterson
-
Sven Panne