Functor => Pointed => Applicative => Monad

Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac: class Functor f where map :: (a -> b) -> f a -> f b class Functor f => Pointed f where pure :: a -> f a class Pointed f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b join :: m (m a) -> m a f >>= x = join (fmap f x) m >> k = m >>= \_ -> k join x = x >>= id This would eliminate the necessity of declaring a Monad instance for every Applicative, and eliminate the need for sets of duplicate functions such as [fmap,liftM,map,liftA], [(<*>),ap], and [concat,join]. fail should be removed from Monad; a failed pattern match could error in the same way as is does for pure code. The only sensible uses for fail seem to be synonyms for mzero.

On 11/29/10 3:39 AM, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
I'm not aware of any intention to do so, but I wholeheartedly approve of doing so. I'd probably leave fmap being called fmap though, in order to minimize breakage. Also, that enables the cute name for class Bifunctor f where gmap :: (a -> b) -> f a c -> f b c -- Live well, ~wren

On 29 November 2010 20:32, wren ng thornton
On 11/29/10 3:39 AM, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
I'm not aware of any intention to do so, but I wholeheartedly approve of doing so. I'd probably leave fmap being called fmap though, in order to minimize breakage. Also, that enables the cute name for
class Bifunctor f where gmap :: (a -> b) -> f a c -> f b c
I would prefer to call that "bimap" or something; to me gmap refers to mapping over a graph. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

Hello wren Convention has Bifunctor as this class: class Bifunctor f where bimap :: (a -> x) -> (b -> y) -> f a b -> f x y Personally I'd like to add these two so they can be optimized if required: mapFst :: (a -> x) -> f a b -> f x b mapSnd :: (b -> y) -> f a b -> f a y Though, I'm sanguine about the names. On pairs mapSnd is fmap, however I'd still like mapSnd in addition to fmap - if I'm working with pairs I'd want the symmetric "vocabulary" of pairs not a pidgin of two vocabularies. Bifunctor is a class I'd really like to see in Base. When working with pairs, I much prefer the notation from Bifunctor to the notations from Control.Categrory & Arrows. Best wishes Stephen

On 29/11/2010 11:32, wren ng thornton wrote:
I'm not aware of any intention to do so, but I wholeheartedly approve of doing so. I'd probably leave fmap being called fmap though, in order to minimize breakage.
fmap = map This could be part of a legacy module, along with any other eliminated duplicated functions. Historical cruft remains in Haskell far too long; is there no desire for an occasional cleanup?

On 29 November 2010 13:28, John Smith
fmap = map
This could be part of a legacy module, along with any other eliminated duplicated functions. Historical cruft remains in Haskell far too long; is there no desire for an occasional cleanup?
Speaking personally, I'm quite happy to have both map and (functorial) fmap. Haskell's intention is to be a "state of the art _functional_ language", so keeping the functional core doesn't seem unwarranted to me. There is the Charity language which was "categorical" first, and "functional" second if people really want a "crystal mountain".

On Mon, 2010-11-29 at 15:30 +0000, Stephen Tetley wrote:
On 29 November 2010 13:28, John Smith
wrote: fmap = map
This could be part of a legacy module, along with any other eliminated duplicated functions. Historical cruft remains in Haskell far too long; is there no desire for an occasional cleanup?
Speaking personally, I'm quite happy to have both map and (functorial) fmap.
Haskell's intention is to be a "state of the art _functional_ language", so keeping the functional core doesn't seem unwarranted to me. There is the Charity language which was "categorical" first, and "functional" second if people really want a "crystal mountain".
While duplicating methods is one side of problem the bigger problem is when you try to write as general as possible and end up with: func1 :: Pointed a => ... func2 :: Applicative a => ... func3 :: (Pointed a, Applicative a, Monad a) => ... -- Uses func1 and func2 + require monad map as (fmap :: (a -> b) -> [a] -> [b]) have it's uses even when Functor => Pointed => Applicative => Monad Regards

On 11/29/10 10:30 AM, Stephen Tetley wrote:
On 29 November 2010 13:28, John Smith
wrote: fmap = map
This could be part of a legacy module, along with any other eliminated duplicated functions. Historical cruft remains in Haskell far too long; is there no desire for an occasional cleanup?
Speaking personally, I'm quite happy to have both map and (functorial) fmap.
Haskell's intention is to be a "state of the art _functional_ language", so keeping the functional core doesn't seem unwarranted to me. There is the Charity language which was "categorical" first, and "functional" second if people really want a "crystal mountain".
Also, e.g., I'll often use "map" when my specific intention is to restrict a type to lists, whereas I use "fmap" when I intend to be general. Similarly for "concat" vs "join". While it is theoretically valuable to see that one is just a specialization of the other, it is practically valuable to make use of that specialization in order to have our programs convey exactly what we mean (instead of what we /could/ mean). While we really like extensionality, intensionality has its place too. -- Live well, ~wren

On Monday 29 November 2010 10:30:57 am Stephen Tetley wrote:
Speaking personally, I'm quite happy to have both map and (functorial) fmap.
Haskell's intention is to be a "state of the art _functional_ language", so keeping the functional core doesn't seem unwarranted to me. There is the Charity language which was "categorical" first, and "functional" second if people really want a "crystal mountain".
There's also a language called Haskell 1.4 in which fmap is called map, among other things. Unfortunately, neither it nor Charity are still developed. -- Dan

On Mon, 2010-11-29 at 10:39 +0200, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
class Pointed f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
a *> b = flip const <$> a <*> b a <* b = const <$> a <*> b
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b join :: m (m a) -> m a
f >>= x = join (fmap f x) m >> k = m >>= \_ -> k join x = x >>= id
This would eliminate the necessity of declaring a Monad instance for every Applicative, and eliminate the need for sets of duplicate functions such as [fmap,liftM,map,liftA], [(<*>),ap], and [concat,join].
Technically (>>) and (*>) are duplicates assumin (<*>) and ap are, I believe: a *> b flip const <$> a <*> b (fmap (flip const) a) <*> b ap (fmap (flip const) a) b liftM2 id (fmap (flip const) a) b (fmap (flip const) a) >>= \a' -> b >>= \b' -> return (id a' b') (fmap (flip const) a) >>= \a' -> b >>= \b' -> return (a' b') a >>= \a' -> b >>= \b' -> return (flip const a' b') a >>= \a' -> b >>= \b' -> return (const b' a') a >>= \a' -> b >>= \b' -> return b' a >>= \a' -> b a >>= \_ -> b a >> b
fail should be removed from Monad; a failed pattern match could error in the same way as is does for pure code. The only sensible uses for fail seem to be synonyms for mzero.
It is discussed for some time on mailing list. However I'm not aware about any movement in this direction. Probably it is because that the Monad is in core of many Haskell libraries from which some do not define Applicative. Possibly it could be tested on Hackage how big impact would be to current packages. Other method would be to have "weak instances" (we inform compiler that the legal, unoptimized implementation must look like this but allow overwritten for performance). Something like: instance weak Monad a => Functor a where fmap = liftM instance weak Monad a => Pointed a where point = return instance weak Monad a => Applicative a where (<*>) = `ap` Regards

On November 29, 2010 08:58:41 Maciej Piechotka wrote:
Probably it is because that the Monad is in core of many Haskell libraries from which some do not define Applicative. Possibly it could be tested on Hackage how big impact would be to current packages.
This shouldn't really be a show stopper though. If you have the code to generate the Monad instance, you already have your Applicative instance f <*> x = do { f' <- f; x' <- x; return $ f x } Presumably, if you wanted to make this change (which I also think is a good idea), you would go through and patch the packages missing this instance first. Cheers! -Tyson

On Mon, 2010-11-29 at 11:00 -0500, Tyson Whitehead wrote:
On November 29, 2010 08:58:41 Maciej Piechotka wrote:
Probably it is because that the Monad is in core of many Haskell libraries from which some do not define Applicative. Possibly it could be tested on Hackage how big impact would be to current packages.
This shouldn't really be a show stopper though. If you have the code to generate the Monad instance, you already have your Applicative instance
f <*> x = do { f' <- f; x' <- x; return $ f x }
Presumably, if you wanted to make this change (which I also think is a good idea), you would go through and patch the packages missing this instance first.
Cheers! -Tyson
I guess the problem is not that it is not possible - the point of this change is that every monad is applicative functor which is pointed functor which is functor. The problem is that it breaks code i.e. code that did compile does not compile any more. While it is possible to automatically 'fix' code on hackage it may not be so easy if the code: - is not distributed via Hackage - license disallows to perform such change except copyright holder I think that the change is good idea but it may cause problems. Regards

On 11/29/10 8:58 AM, Maciej Piechotka wrote:
class Pointed f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
a *> b = flip const<$> a<*> b a<* b = const<$> a<*> b
I assume you're meaning default implementations, rather than that they should be removed from the class? (the reason to be in the class is performance issues.)
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b join :: m (m a) -> m a
f>>= x = join (fmap f x) m>> k = m>>= \_ -> k join x = x>>= id
This would eliminate the necessity of declaring a Monad instance for every Applicative, and eliminate the need for sets of duplicate functions such as [fmap,liftM,map,liftA], [(<*>),ap], and [concat,join].
Technically (>>) and (*>) are duplicates assumin (<*>) and ap are, I believe:
Yes. Assuming the free applicative instance from the monad ---with pure=return; (<*>)=ap--- then (>>) = (*>). Due to legacy reasons it might be nice to keep both names around since (>>) looks like (>>=), whereas (*>) looks like (<*>) and the related (<*) ---which is not (<<). Perhaps we should just move (>>) out of Monad via: (>>) :: (Monad m) => m a -> m b -> m b (>>) = (*>) Which fits with (=<<), (<<), (<=<), and (>=>) being outside of the class too. -- Live well, ~wren

On 11/29/10 03:39, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
Is it useful to have Pointed non-Functors? (I.e. not superclass). Er, Data.Set is the only example I've come up with (its 'singleton' doesn't require Ord on elements but its 'map' does). Then you'd have things like class (Pointed f, Functor f) => Applicative f where Cons: Pointed doesn't have any laws without Functor Pros: (pure) might be useful to use generically by itself -Isaac

On Mon, Nov 29, 2010 at 11:26 AM, Isaac Dupree
On 11/29/10 03:39, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
Is it useful to have Pointed non-Functors?
Is Pointed useful at all? The last time this discussion came up, I
asked for algorithms which were generic over pointed functors (in the
same way that traverse is generic over applicative functors) and no
one could think of any.
Without <*> or >>=, all we can say about pure is that it's a natural
transformation.
--
Dave Menendez

On Mon, Nov 29, 2010 at 7:46 PM, David Menendez
On Mon, Nov 29, 2010 at 11:26 AM, Isaac Dupree
wrote: On 11/29/10 03:39, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
Is it useful to have Pointed non-Functors?
Is Pointed useful at all? The last time this discussion came up, I asked for algorithms which were generic over pointed functors (in the same way that traverse is generic over applicative functors) and no one could think of any.
Without <*> or >>=, all we can say about pure is that it's a natural transformation.
It would be useful for the Failure typeclass[1]. As-is, we made Monad the superclass just for ease of use, but there could definitely be some non-Monads for which a Failure instance makes sense. I think the one that occurred to me most recently is forms in Yesod, which have an Applicative but not Monad instance. Michael [1] http://hackage.haskell.org/packages/archive/failure/0.1.0.1/doc/html/Control...

On Mon, Nov 29, 2010 at 3:50 PM, Michael Snoyman
It would be useful for the Failure typeclass[1]. As-is, we made Monad the superclass just for ease of use, but there could definitely be some non-Monads for which a Failure instance makes sense. I think the one that occurred to me most recently is forms in Yesod, which have an Applicative but not Monad instance.
OP's proposal is to have class Applicative m => Monad m where ... so you could just say class Applicative f => Failure e f where ... The question is if there is something that is Pointed but not Applicative that we would like to be Failure. Cheers! =) -- Felipe.

On Mon, Nov 29, 2010 at 8:19 PM, Felipe Almeida Lessa
On Mon, Nov 29, 2010 at 3:50 PM, Michael Snoyman
wrote: It would be useful for the Failure typeclass[1]. As-is, we made Monad the superclass just for ease of use, but there could definitely be some non-Monads for which a Failure instance makes sense. I think the one that occurred to me most recently is forms in Yesod, which have an Applicative but not Monad instance.
OP's proposal is to have
class Applicative m => Monad m where ...
so you could just say
class Applicative f => Failure e f where ...
The question is if there is something that is Pointed but not Applicative that we would like to be Failure.
That's true for the case of forms, but there is definitely something appealing about having Pointed separate. I may not be able to think of an example where I'd want a Failure instance that isn't Applicative, but you never know ;). Michael

On Mon, Nov 29, 2010 at 12:46:28PM -0500, David Menendez wrote:
On Mon, Nov 29, 2010 at 11:26 AM, Isaac Dupree
Is it useful to have Pointed non-Functors?
Is Pointed useful at all? The last time this discussion came up, I asked for algorithms which were generic over pointed functors (in the same way that traverse is generic over applicative functors) and no one could think of any.
fromFoldable :: (Foldable f, Pointed g, Monoid (g a)) => f a -> g a fromFoldable = foldMap pure

On Mon, 2010-11-29 at 18:36 +0000, Ross Paterson wrote:
On Mon, Nov 29, 2010 at 12:46:28PM -0500, David Menendez wrote:
On Mon, Nov 29, 2010 at 11:26 AM, Isaac Dupree
Is it useful to have Pointed non-Functors?
Is Pointed useful at all? The last time this discussion came up, I asked for algorithms which were generic over pointed functors (in the same way that traverse is generic over applicative functors) and no one could think of any.
fromFoldable :: (Foldable f, Pointed g, Monoid (g a)) => f a -> g a fromFoldable = foldMap pure
One instance `g` of `Pointed` where this is useful is the type constructor for difference lists (aka functional lists) which does provide singleton and monoid operations but no map function without converting to ordinary lists. With regard to laws one could still 'require' laws for the interaction of `Functor` and `Pointed` if both instances are defined. Sebastian

David Menendez wrote:
On Mon, Nov 29, 2010 at 11:26 AM, Isaac Dupree
Is it useful to have Pointed non-Functors?
Is Pointed useful at all? The last time this discussion came up, I asked for algorithms which were generic over pointed functors (in the same way that traverse is generic over applicative functors) and no one could think of any.
I remember that I have recently abused Applicative in connection with Traversable in order to get the 'pure' method. First example: A general implementation of a 'peek' for traversable structures: http://hackage.haskell.org/packages/archive/storable-record/0.0.2.3/doc/html... Second example: The liftPoint function in http://code.haskell.org/~thielema/streamed/src/Sound/MIDI/ALSA/Causal.hs that lifts a not-quite arrow (T a b) to a (T (t a) (t b)) where 't' is Traversable.

On November 29, 2010 11:26:34 Isaac Dupree wrote:
On 11/29/10 03:39, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
Is it useful to have Pointed non-Functors? (I.e. not superclass). Er, Data.Set is the only example I've come up with (its 'singleton' doesn't require Ord on elements but its 'map' does). Then you'd have things like
class (Pointed f, Functor f) => Applicative f where
I've wondered about the ordering of Pointed/Functor for awhile. Lifting of a type would seem to be something that would require less machinery (i.e., impose less structure) than lifting a function to work over lifted types. I would think this should imply the later is more specialized and should at minimum not appear further up the class hierarchy (as proposed). As to whether it should go (Pointed, Functor) => Applicative or Pointed => Functor => Applicative, it would seem to me that, just as when given a Monad I have Applicative, when given a Functor I have Pointed pure x = fmap (const x) undefined Presuming (without proof) that this is the only valid definition given the underlying laws, perhaps it should then go Pointed => Functor => Applicative. Cheers! -Tyson

On Mon, Nov 29, 2010 at 1:08 PM, Tyson Whitehead
On November 29, 2010 11:26:34 Isaac Dupree wrote:
On 11/29/10 03:39, John Smith wrote:
Is there any intention to reorganise the standard class hierarchy, arranging them logically instead of in order of invention? I plagiarised the following example from http://stackoverflow.com/questions/1634911/can-liftm-differ-from-lifta and Trac:
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Pointed f where pure :: a -> f a
Is it useful to have Pointed non-Functors? (I.e. not superclass). Er, Data.Set is the only example I've come up with (its 'singleton' doesn't require Ord on elements but its 'map' does). Then you'd have things like
class (Pointed f, Functor f) => Applicative f where
I've wondered about the ordering of Pointed/Functor for awhile.
Lifting of a type would seem to be something that would require less machinery (i.e., impose less structure) than lifting a function to work over lifted types. I would think this should imply the later is more specialized and should at minimum not appear further up the class hierarchy (as proposed).
As to whether it should go (Pointed, Functor) => Applicative or Pointed => Functor => Applicative, it would seem to me that, just as when given a Monad I have Applicative, when given a Functor I have Pointed
pure x = fmap (const x) undefined
Presuming (without proof) that this is the only valid definition given the underlying laws, perhaps it should then go Pointed => Functor => Applicative.
Cheers! -Tyson
Tthere are instances of Functor that are not pointed - as in, most of Control.Comonad.*. So I don't think that Pointed should be a constraint on Functor. The real question is if Functor should be a contraint on Pointed. Antoine

On November 29, 2010 14:08:16 Tyson Whitehead wrote:
As to whether it should go (Pointed, Functor) => Applicative or Pointed => Functor => Applicative, it would seem to me that, just as when given a Monad I have Applicative, when given a Functor I have Pointed
pure x = fmap (const x) undefined
Presuming (without proof) that this is the only valid definition given the underlying laws, perhaps it should then go Pointed => Functor => Applicative.
Actually, I see this definition has problems as fmap likely has to take apart "undefined" in order to apply it to "const x". Still, it is interesting. It really seem to me that the Functor machinery should be a level up in complexity from the Pointed machinery (i.e., I would expect more things to be Pointed than Functors). I wonder if fmap plus a bit (such as a single value like "pure ()" to use instead of undefined) would entirely nails down pure. Cheers! -Tyson

On 11/29/10 2:08 PM, Tyson Whitehead wrote:
As to whether it should go (Pointed, Functor) => Applicative or Pointed => Functor => Applicative, it would seem to me that,
Not all functors are pointed therefore Pointed=>Functor is invalid. Leaving them unordered or requiring Functor=>Pointed are the only options. Essentially, for T :: * -> *, pointedness is saying that there is a trivial embedding of the parameter, a, into T a; whereas functoriality is saying that T is structural over its parameter. Surely the latter is "more complicated", but they're rather different concepts. -- Live well, ~wren

On November 30, 2010 00:32:18 wren ng thornton wrote:
Essentially, for T :: * -> *, pointedness is saying that there is a trivial embedding of the parameter, a, into T a; whereas functoriality is saying that T is structural over its parameter. Surely the latter is "more complicated", but they're rather different concepts.
Hi Wren, I always enjoy your input. Would you be able to expound on the intuition behind "functoriality is saying that T is structural over its parameter"? (I don't think I'm following what you mean by "stuctural over its parameter") Thanks! -Tyson

On 12/2/10 4:41 PM, Tyson Whitehead wrote:
On November 30, 2010 00:32:18 wren ng thornton wrote:
Essentially, for T :: * -> *, pointedness is saying that there is a trivial embedding of the parameter, a, into T a; whereas functoriality is saying that T is structural over its parameter. Surely the latter is "more complicated", but they're rather different concepts.
Hi Wren,
I always enjoy your input.
Thanks :)
Would you be able to expound on the intuition behind "functoriality is saying that T is structural over its parameter"?
(I don't think I'm following what you mean by "stuctural over its parameter")
Well the paradigmatic (programming) examples of functors are all container-like structures: sets, multisets, lists, trees,... If we look at those functors more closely, they all have a familiar form. In particular they are all some kind of "structure", typically a set-theoretic or graphical structure built on top of some values of the parameter type. But the structure itself does not care what the parameter type is because it never peers inside those values--- it's just some kind of scaffolding that sits atop the parametric holes. So functors just build up some kind of structure on top of its parameter.[1] This sort of parametricity is required for all functors, in fact it is exactly this requirement that is captured by the type fmap@F :: forall a b. (a->b) -> F a -> F b, with the associated functor laws. The functor laws are there to prevent vacuous or trivial definitions of the type (e.g., taking every F a to the empty F b), in order to ensure that the definition of fmap behaves in the way we expect for structures over an arbitrary type. The intuition of functors capturing structure is closely related to the intuition of monads capturing structure[2]. The dual intuition is that functors capture context (a la comonads capture context). When expressed as an intuition about functors, these are the same idea, since we like to think of contexts as structures with holes in them where the structure doesn't care about what fills the holes. [1] Though note that these aren't necessarily structures over the *values* of the parameter. For example, the vacuous functor: data Vac a = Vac instance Functor Vac where fmap f Vac = Vac But there are more interesting examples too (non-pointed ones even): data SliceOver a b = SliceOver (a->b) instance Functor (SliceOver a) where fmap f (SliceOver g) = SliceOver (f . g) data SliceUnder a b = SliceUnder (b->a) instance Functor (SliceUnder a) where fmap f (SliceUnder g) = SliceUnder (g . f) [2] As opposed to the intuition of monads as capturing control. -- Live well, ~wren

On 4 Dec 2010, at 06:25, wren ng thornton wrote:
Well the paradigmatic (programming) examples of functors are all container-like structures: sets, multisets, lists, trees,...
Really? Just as monads are not (only) containers, I think it is a mistake to think of functors as (only) containers too. There are many common paradigmatic examples of "active" functors as well: parsers, pretty-printers, database queries. Regards, Malcolm

On 12/4/10 12:31 PM, Malcolm Wallace wrote:
On 4 Dec 2010, at 06:25, wren ng thornton wrote:
Well the paradigmatic (programming) examples of functors are all container-like structures: sets, multisets, lists, trees,...
Really? Just as monads are not (only) containers, I think it is a mistake to think of functors as (only) containers too.
I never said they were only containers, I said that the paradigmatic ones for programming (i.e., the first examples cited) tend to be. Parsers, continuations, and the like tend to come afterwards--- once people have already become familiar with the basic idea of functors. I think one of the telling things about containers (as a subclass of functors) is that, while most of them form co/monads, we tend to think about them more primarily as functors, i.e. as things with stuff inside that we can change homogeneously. Whereas parsers and the like are more often thought of first as applicative/monadic structures and the functorality just comes along for the ride. -- Live well, ~wren

Regarding recent concerns as to whether Pointed is actually useful (and if it is, is that Pointed Functors or pure Pointed?), how about a slightly more modest reform? class Functor f where map :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b f >>= x = join $ map f x join :: m (m a) -> m a join x = x >>= id (unrelated, but also valid) instance MonadPlus m => Monoid (m a) where mempty = mzero mappend = mplus module Legacy where fmap :: Functor f => (a -> b) -> f a -> f b fmap = map liftA :: Applicative f => (a -> b) -> f a -> f b liftA = map liftM :: Monad m => (a -> b) -> m a -> m b liftM = map ap :: Monad m => m (a -> b) -> m a -> m b ap = (<*>) (>>) :: Monad m => m a -> m b -> m b (>>) = (*>) concat :: [[a]] -> [a] concat = join etc. And for those who really want a list map, listMap :: (a -> b) -> [a] -> [b] listMap = map

This proposal now has a Wiki page http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal

On 6 Dec 2010, at 14:09, John Smith wrote:
This proposal now has a Wiki page http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal
See also Ashley Yakeley's http://www.haskell.org/haskellwiki/Functor_hierarchy_proposal Cheers Conor

Me thinks there's more value that "the next language after Haskell" might have such a hierarchy than Haskell itself. At Haskell 1.3 I think there was one text book (Davie), possibly none at Haskell 1.4 and many at Haskell 98. The value of invalidating 12 or so years of documentation for "logic" seems somewhat questionable from my perspective. If either proposal were limited to just adding class constraints to get the desired hierarchy rather than eliminating methods, they might have more legs...

On Mon, 2010-12-06 at 15:47 +0000, Stephen Tetley wrote:
Me thinks there's more value that "the next language after Haskell" might have such a hierarchy than Haskell itself.
At Haskell 1.3 I think there was one text book (Davie), possibly none at Haskell 1.4 and many at Haskell 98. The value of invalidating 12 or so years of documentation for "logic" seems somewhat questionable from my perspective. If either proposal were limited to just adding class constraints to get the desired hierarchy rather than eliminating methods, they might have more legs...
As far as I understend you, you would prefer: class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a class Applicative m => Monad m where (>>) :: m a -> m b -> m b (>>) = (*>) (>>=) :: m a -> (a -> m b) -> m b f >>= x = join $ map f x return :: a -> m a return = pure join :: m (m a) -> m a join x = x >>= id or. class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Pointed f where point :: a -> f a class Pointed f => Applicative f where pure :: a -> f a pure = point (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a class Applicative m => Monad m where (>>) :: m a -> m b -> m b (>>) = (*>) (>>=) :: m a -> (a -> m b) -> m b f >>= x = join $ map f x return :: a -> m a return = pure join :: m (m a) -> m a join x = x >>= id Regards

On 6 Dec 2010, at 15:47, Stephen Tetley wrote:
Me thinks there's more value that "the next language after Haskell" might have such a hierarchy than Haskell itself.
I should advise anyone designing the next language after Haskell to think about these issues and a great deal more, when it comes to organising functorial structure and programming with computational effects.
At Haskell 1.3 I think there was one text book (Davie), possibly none at Haskell 1.4 and many at Haskell 98. The value of invalidating 12 or so years of documentation for "logic" seems somewhat questionable from my perspective. If either proposal were limited to just adding class constraints to get the desired hierarchy rather than eliminating methods, they might have more legs...
Right. This issue is often mentioned as a motivating example for various language proposals to allow superclass method definitions in instance declarations and indeed default superclass instances in subclass declarations. I don't know the status of these proposals, and what else they're trying to achieve besides the telescoping of multiple instance declarations. I'd like to be able to say something like class Functor f where fmap :: (s -> t) -> f s -> f t class Functor f => Applicative f where return :: x -> f x (<*>) :: f (s -> t) -> f s -> f t instance Functor f where fmap = (<*>) . return class Applicative f => Monad f where (>>=) :: f s -> (s -> f t) -> f t instance Applicative f where ff <*> fs = ff >>= \ f -> fs >>= \ s -> return (f s) (possibly without the duplicated constraint) then declare Monad instances as before, and collect all three. The obvious dumb way to unpack these compound declarations would be to generate a superclass instance from each subclass instance according to the scheme supplied in the class (overriding defaults as demanded). I'm sure that's hopelessly naive for reasons I'm just too, er, hopelessly naive to see right now. It does, however, have the merit of requiring only the awareness of which methods belong to which class and a spot of textual rearrangement, to be delivered on top of Haskell as it stands. Does anybody have a Haskell preprocessor they could just hack this into for a laugh over Chrimbo? Cheers Conor

On 06/12/2010 17:47, Stephen Tetley wrote:
Me thinks there's more value that "the next language after Haskell" might have such a hierarchy than Haskell itself.
At Haskell 1.3 I think there was one text book (Davie), possibly none at Haskell 1.4 and many at Haskell 98. The value of invalidating 12 or so years of documentation for "logic" seems somewhat questionable from my perspective. If either proposal were limited to just adding class constraints to get the desired hierarchy rather than eliminating methods, they might have more legs...
.NET and Java are used in billions of line of production code and have thousands of books written about them, but new versions often obsolete what would have previously been recommended practice. Breaking legacy documentation is generally the least of anyone's worries when moving a language forward. As for breaking code, new versions of GHC often break a bunch of packages (see the build logs on hackage), although the breakage would be more pervasive in this case. As for eliminating methods, I'm only proposing that they be moved into a legacy module (as was done with old-time and OldException), so the classic functions will still be available.

On Mon, Dec 6, 2010 at 19:22, John Smith wrote:
.NET and Java are used in billions of line of production code and have thousands of books written about them, but new versions often obsolete what would have previously been recommended practice. Breaking legacy documentation is generally the least of anyone's worries when moving a language forward.
As for breaking code, new versions of GHC often break a bunch of packages (see the build logs on hackage), although the breakage would be more pervasive in this case.
These two statements do not help your argument. "Other people do it, so it's okay if we do it, too" is not sufficient reason for breaking working programs and invalidating textbooks. This appeal to popularity[1] is false: Microsoft and Sun/Oracle certainly care about backwards compatibility, and the GHC developers do, too (cf. move from base-3 to base 4). As for eliminating methods, I'm only proposing that they be moved into a
legacy module (as was done with old-time and OldException), so the classic functions will still be available.
The _use_ of these functions may only require an additional 'import' of said legacy module, but the _definitions_ of type class instances will be broken. Regards, Sean [1] http://www.logicalfallacies.info/relevance/appeals/appeal-to-popularity/

On 06/12/2010 20:44, Sean Leather wrote:
.NET and Java are used in billions of line of production code and have thousands of books written about them, but new versions often obsolete what would have previously been recommended practice. Breaking legacy documentation is generally the least of anyone's worries when moving a language forward.
As for breaking code, new versions of GHC often break a bunch of packages (see the build logs on hackage), although the breakage would be more pervasive in this case.
These two statements do not help your argument. "Other people do it, so it's okay if we do it, too" is not sufficient reason for breaking working programs and invalidating textbooks. This appeal to popularity[1] is false: Microsoft and Sun/Oracle certainly care about backwards compatibility, and the GHC developers do, too (cf. move from base-3 to base 4).
My anecdotal experience is that developers much prefer the .NET/Java approach in this regard, but I'm not aware of a formal survey. I would say that appeal to popularity is entirely the point here. We are not determining facts, but what users would prefer - introduce breaking changes (with a specified benefit), or stick to compatibility with old documentation.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 12/6/10 13:50 , John Smith wrote:
My anecdotal experience is that developers much prefer the .NET/Java approach in this regard, but I'm not aware of a formal survey.
Agreeed. Put more concretely, developers strongly prefer that ugly warts in the language be *fixed*, even at the expense of backward compatibility. Java, in particular, breaks things because a sufficient number of developers have asked that backward compatibility be discarded in favor of fixes. Also agreed that popularity is indeed *the* point. The developers are your customers; ignoring your customers' requests, in general, is a BAD thing. - -- brandon s. allbery [linux,solaris,freebsd,perl] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkz9XF4ACgkQIn7hlCsL25WdZgCgpMSwTDiBBTMZG8HxuEgWG7D+ HzoAoJkYrNpjLx3ycfnFKx06obhUJg5v =5Q5h -----END PGP SIGNATURE-----

On 6 December 2010 21:57, Brandon S Allbery KF8NH
Agreeed. Put more concretely, developers strongly prefer that ugly warts in the language be *fixed*, even at the expense of backward compatibility. Java, in particular, breaks things because a sufficient number of developers have asked that backward compatibility be discarded in favor of fixes.
I'm not surprised that developers want ugly warts fixed, my contention is that developers have overlooked that this change [*] has a different magnitude to themselves compared to educators / authors and beginners. [*] Personally I don't consider the status quo here to be an ugly wart. The redundancy of notations between Applicative and Monad has useful separation of Applicative and Monadic styles for *current* Haskell. If Post-Haskell or even Haskell'2012 wants to merge the styles to "bind only when you need to" that's fine but the new language is obliged to create the tutorials, text books, write the conference papers in the new style, etc.

On 7 Dec 2010, at 09:00, Stephen Tetley wrote:
[*] Personally I don't consider the status quo here to be an ugly wart. The redundancy of notations between Applicative and Monad has useful separation of Applicative and Monadic styles for *current* Haskell.
Perhaps I'm a statistical outlier, but I find this separation highly counterproductive, both when I try to teach it and when I come to use it. These days, I write a lot of almost entirely pure HTML-generating code, sparsely peppered with effectful incidents (read CGI input, mark it wrong, etc). My code splits into two ill-connected chunks: a do-block which generates the interactive nuggets, then a whole sodding web page after the return. It's awful. Change cannot come too soon!
If Post-Haskell or even Haskell'2012 wants to merge the styles to "bind only when you need to" that's fine but the new language is obliged to create the tutorials, text books, write the conference papers in the new style, etc.
Indeed. We need to manage change carefully, hence this discussion. If we could clarify the direction of travel, that would certainly help. It's not at all obvious to me that we should make the Functor => Applicative => Monad change in isolation, but we should certainly be looking to deliver that change and others in a coherent manner. All the best Conor

On 12/6/10 9:48 AM, Conor McBride wrote:
On 6 Dec 2010, at 14:09, John Smith wrote:
This proposal now has a Wiki page http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal
I, like Ashley Yakeley, prefer the name "return" for this context. The name "pure" suggests that applicatives/monads are inherently impure, when in fact they are generally pure. Also the name "return" was chosen specifically because of its similarity to (in spite of its difference from) the imperative keyword, as well as the suggestion of its forming the simplest 'program'--- following the idea of monads as building up programs for executing later. The name "pure" for applicatives has historically conflicted with the similar function for the arrows class (where I think "pure" is a better name than "arr"), and AFAIK applicatives took the name largely because they couldn't reuse "return". Also, there's a difference between breaking legacy code for legitimate improvements (e.g., Applicative=>Monad) vs breaking it just for the sake of breaking it. -- Live well, ~wren

On Wed, Dec 1, 2010 at 10:02 AM, John Smith
Regarding recent concerns as to whether Pointed is actually useful (and if it is, is that Pointed Functors or pure Pointed?), how about a slightly more modest reform?
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b f >>= x = join $ map f x
join :: m (m a) -> m a join x = x >>= id
(unrelated, but also valid)
instance MonadPlus m => Monoid (m a) where mempty = mzero mappend = mplus
module Legacy where
fmap :: Functor f => (a -> b) -> f a -> f b fmap = map
liftA :: Applicative f => (a -> b) -> f a -> f b liftA = map
liftM :: Monad m => (a -> b) -> m a -> m b liftM = map
ap :: Monad m => m (a -> b) -> m a -> m b ap = (<*>)
(>>) :: Monad m => m a -> m b -> m b (>>) = (*>)
concat :: [[a]] -> [a] concat = join
etc.
And for those who really want a list map,
listMap :: (a -> b) -> [a] -> [b] listMap = map
Linked are some patch bundles that provide an initial implementation of the new hierarchy: * http://code.haskell.org/~basvandijk/ghc_new_monad_hierarchy.dpatch This patch bundle is to prepare ghc for the new hierarchy. Most importantly it adds Functor and Applicative instances for all monads in ghc. Note that these patches are useful on their own and don't depend on the new hierarchy so they can be applied even when this proposal is not accepted. * http://code.haskell.org/~basvandijk/base_new_monad_hierarchy.dpatch This patch actually implements the new hierarchy. I tried to be even more conservative than the current proposal, namely 'return' and '>>' are still methods of Monad but have now been given default implementations in terms of Applicative. Also all names have been kept intact (fmap is still named fmap): class Functor f where fmap :: (a -> b) -> f a -> f b (<$) :: a -> f b -> f a (<$) = fmap . const class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b a *> b = fmap (const id) a <*> b (<*) :: f a -> f b -> f a a <* b = fmap const a <*> b class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b m >>= f = join $ fmap f m join :: m (m a) -> m a join m = m >>= id (>>) :: m a -> m b -> m b (>>) = (*>) return :: a -> m a return = pure fail :: String -> m a fail s = error s Also see the generated library documentation: http://bifunctor.homelinux.net/~bas/doc/ghc/html/libraries/base-4.4.0.0/ Note that I am in favour of removing 'return', '>>' and 'fail' from Monad and renaming 'fmap' to 'map'. But I think it's better to do this as a separate patch. Besides patching the base library and ghc, I also needed to patch lots of other libraries in my ghc root. To get these patches, simply pull from my local ghc repository. i.e.: darcs pull http://bifunctor.homelinux.net/~bas/ghc/ darcs pull http://bifunctor.homelinux.net/~bas/ghc/libraries/base Note that ghc requires the happy parser generator. When happy generates a parser it also generates a HappyIdentity type with an according Monad instance. The following patch makes happy also generate the needed Functor and Applicative instances (This patch is already send to happy's maintainer): http://bifunctor.homelinux.net/~bas/functor_and_applicative_instance_HappyId... Feel free to ask questions or post comments about these patches. Regards, Bas P.S. John, did you already make a ticket for this proposal? I would like to attach my patches to it.

There's a ticket at http://trac.haskell.org/haskell-platform/ticket/155, and a wiki page at http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal. Thanks for your patches! On 12/12/2010 13:12, Bas van Dijk wrote:
On Wed, Dec 1, 2010 at 10:02 AM, John Smith
wrote: Regarding recent concerns as to whether Pointed is actually useful (and if it is, is that Pointed Functors or pure Pointed?), how about a slightly more modest reform?
class Functor f where map :: (a -> b) -> f a -> f b
class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b (<*) :: f a -> f b -> f a
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b f>>= x = join $ map f x
join :: m (m a) -> m a join x = x>>= id
(unrelated, but also valid)
instance MonadPlus m => Monoid (m a) where mempty = mzero mappend = mplus
module Legacy where
fmap :: Functor f => (a -> b) -> f a -> f b fmap = map
liftA :: Applicative f => (a -> b) -> f a -> f b liftA = map
liftM :: Monad m => (a -> b) -> m a -> m b liftM = map
ap :: Monad m => m (a -> b) -> m a -> m b ap = (<*>)
(>>) :: Monad m => m a -> m b -> m b (>>) = (*>)
concat :: [[a]] -> [a] concat = join
etc.
And for those who really want a list map,
listMap :: (a -> b) -> [a] -> [b] listMap = map
Linked are some patch bundles that provide an initial implementation of the new hierarchy:
* http://code.haskell.org/~basvandijk/ghc_new_monad_hierarchy.dpatch
This patch bundle is to prepare ghc for the new hierarchy. Most importantly it adds Functor and Applicative instances for all monads in ghc. Note that these patches are useful on their own and don't depend on the new hierarchy so they can be applied even when this proposal is not accepted.
* http://code.haskell.org/~basvandijk/base_new_monad_hierarchy.dpatch
This patch actually implements the new hierarchy. I tried to be even more conservative than the current proposal, namely 'return' and '>>' are still methods of Monad but have now been given default implementations in terms of Applicative. Also all names have been kept intact (fmap is still named fmap):
class Functor f where fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a (<$) = fmap . const
class Functor f => Applicative f where pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b a *> b = fmap (const id) a<*> b
(<*) :: f a -> f b -> f a a<* b = fmap const a<*> b
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b m>>= f = join $ fmap f m
join :: m (m a) -> m a join m = m>>= id
(>>) :: m a -> m b -> m b (>>) = (*>)
return :: a -> m a return = pure
fail :: String -> m a fail s = error s
Also see the generated library documentation:
http://bifunctor.homelinux.net/~bas/doc/ghc/html/libraries/base-4.4.0.0/
Note that I am in favour of removing 'return', '>>' and 'fail' from Monad and renaming 'fmap' to 'map'. But I think it's better to do this as a separate patch.
Besides patching the base library and ghc, I also needed to patch lots of other libraries in my ghc root. To get these patches, simply pull from my local ghc repository. i.e.:
darcs pull http://bifunctor.homelinux.net/~bas/ghc/ darcs pull http://bifunctor.homelinux.net/~bas/ghc/libraries/base
Note that ghc requires the happy parser generator. When happy generates a parser it also generates a HappyIdentity type with an according Monad instance. The following patch makes happy also generate the needed Functor and Applicative instances (This patch is already send to happy's maintainer):
http://bifunctor.homelinux.net/~bas/functor_and_applicative_instance_HappyId...
Feel free to ask questions or post comments about these patches.
Regards,
Bas
P.S. John, did you already make a ticket for this proposal? I would like to attach my patches to it.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Sun, Dec 12, 2010 at 12:48 PM, John Smith
There's a ticket at http://trac.haskell.org/haskell-platform/ticket/155,
Thanks! But why create a ticket for the Haskell Platform? This is a change in the base library so we should follow the library submission process[1] and create[2] a ticket in the ghc trac. Regards, Bas [1] http://www.haskell.org/haskellwiki/Library_submissions [2] http://hackage.haskell.org/trac/ghc/newticket?type=proposal&component=libraries/base&milestone=Not+GHC

On 12/12/2010 15:12, Bas van Dijk wrote:
On Sun, Dec 12, 2010 at 12:48 PM, John Smith
wrote: There's a ticket at http://trac.haskell.org/haskell-platform/ticket/155,
Thanks! But why create a ticket for the Haskell Platform? This is a change in the base library so we should follow the library submission process[1] and create[2] a ticket in the ghc trac.
Regards,
Bas
[1] http://www.haskell.org/haskellwiki/Library_submissions [2] http://hackage.haskell.org/trac/ghc/newticket?type=proposal&component=libraries/base&milestone=Not+GHC
Good point; I've moved it to http://hackage.haskell.org/trac/ghc/ticket/4834

Is there a discussion deadline, if this now a libraries proposal?
For something like this, you might want to advertise the discussion on
Plane Haskell, and the -cafe to get adequate discussion, as it seems
sure to break quite a few things. And reddit, although I consider that
a less contemplative venue. Maybe other places?
Do we know of any cases where this sort of conversion will be hard to do?
This is also usually the part of the discussion where I would ask for
an estimate as to how much this breaks what is published on Hackage,
but I think the answer would be "a lot." If I depend on a prior
version of the 'base' package, I'm guessing that I'm not insulated
from this change, due to how de-sugaring happens.
Do other haskell compilers (Hugs, NHC?) use the base library? How does
this change affect them?
Are there any ways to make this sort of change not break things? There
has been talk about a language extensions to make this thing work out,
but they have never been fleshed out, and they've always been the sort
that sounded like they would have many corner cases.
I don't like breaking things, even though the new hierarchy makes a
lot of sense.
Antoine
On Sun, Dec 12, 2010 at 7:24 AM, John Smith
On 12/12/2010 15:12, Bas van Dijk wrote:
On Sun, Dec 12, 2010 at 12:48 PM, John Smith
wrote: There's a ticket at http://trac.haskell.org/haskell-platform/ticket/155,
Thanks! But why create a ticket for the Haskell Platform? This is a change in the base library so we should follow the library submission process[1] and create[2] a ticket in the ghc trac.
Regards,
Bas
[1] http://www.haskell.org/haskellwiki/Library_submissions [2] http://hackage.haskell.org/trac/ghc/newticket?type=proposal&component=libraries/base&milestone=Not+GHC
Good point; I've moved it to http://hackage.haskell.org/trac/ghc/ticket/4834
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

I wanted some more discussion before making a formal proposal - as you point out, there's a lot to consider. Cross-posting to cafe. On 12/12/2010 19:33, Antoine Latter wrote:
Is there a discussion deadline, if this now a libraries proposal?
For something like this, you might want to advertise the discussion on Plane Haskell, and the -cafe to get adequate discussion, as it seems sure to break quite a few things. And reddit, although I consider that a less contemplative venue. Maybe other places?
Do we know of any cases where this sort of conversion will be hard to do?
This is also usually the part of the discussion where I would ask for an estimate as to how much this breaks what is published on Hackage, but I think the answer would be "a lot." If I depend on a prior version of the 'base' package, I'm guessing that I'm not insulated from this change, due to how de-sugaring happens.
Do other haskell compilers (Hugs, NHC?) use the base library? How does this change affect them?
Are there any ways to make this sort of change not break things? There has been talk about a language extensions to make this thing work out, but they have never been fleshed out, and they've always been the sort that sounded like they would have many corner cases.
I don't like breaking things, even though the new hierarchy makes a lot of sense.
Antoine
<snip> Good point; I've moved it to http://hackage.haskell.org/trac/ghc/ticket/4834

On 12/12/10 12:33, Antoine Latter wrote:
Are there any ways to make this sort of change not break things? There has been talk about a language extensions to make this thing work out, but they have never been fleshed out, and they've always been the sort that sounded like they would have many corner cases.
We could add a warning to GHC, "warning: Monad instance exists in this module without corresponding Applicative and Functor instance" and the like. Then change could be more gradual (e.g. people might apply things like your ghc-patch, base-patch, etc. that increase compatibility). (Not sure if it's a good idea, just throwing it out there.) We should also check the performance, if using default method definitions of any stripe. Many things rely on good Monad performance at least. -Isaac

I suspect there are few "modern" Monad instances that aren't already Functor and Applicative [*]. Where I see the change to the hierarchy being problematic is it out dates an awful lot of documentation especially text books which do cover the Monad type class (Monad is much more central to the teaching than say Data.Time or exceptions - old exceptions were in RWH but perhaps not featured elsewhere). You can't apply patches to books - the only mitigation you can perform is to make changes as the language standard changes. Then there's the second issue of renaming functions and eliminating duplicates - perhaps 2 proposals would have been better? [*] For some definition of modern - the only one I can think of that I use is Andy Gill's Dot Monad which is a State-Writer monad, monadic bind within the do-notation is the "trick" to make this Monad elegant and usable.

On Sun, Dec 12, 2010 at 6:16 PM, Stephen Tetley
You can't apply patches to books - the only mitigation you can perform is to make changes as the language standard changes.
An alternative would be to propose this for Haskell 2011 or Haskell 2012. -- Felipe.

On 12/12/2010 22:33, Felipe Almeida Lessa wrote:
On Sun, Dec 12, 2010 at 6:16 PM, Stephen Tetley
wrote: You can't apply patches to books - the only mitigation you can perform is to make changes as the language standard changes.
An alternative would be to propose this for Haskell 2011 or Haskell 2012.
The Haskell committee won't accept a significant change until at least one compiler (usually GHC) has already implemented it.

On 13 December 2010 07:48, John Smith
The Haskell committee won't accept a significant change until at least one compiler (usually GHC) has already implemented it.
That's the operating principle at least for language extensions where it is obviously sensible (don't standardized on vapour ware!). For library changes, which last time around were punted to so time into the future by the committee, the situation seems a bit more nuanced and maybe the committee needs a separate operating principle.
participants (21)
-
Antoine Latter
-
Bas van Dijk
-
Brandon S Allbery KF8NH
-
Conor McBride
-
Dan Doel
-
David Menendez
-
Felipe Almeida Lessa
-
Henning Thielemann
-
Isaac Dupree
-
Ivan Lazar Miljenovic
-
Jean-Philippe Bernardy
-
John Smith
-
Maciej Piechotka
-
Malcolm Wallace
-
Michael Snoyman
-
Ross Paterson
-
Sean Leather
-
Sebastian Fischer
-
Stephen Tetley
-
Tyson Whitehead
-
wren ng thornton