Why isn't mappend for Query flipped?

In XMonad.Core, we have type ManageHook = Query (Endo WindowSet) newtype Query a = Query (ReaderT Window X a) deriving (Functor, Monad, MonadReader Window, MonadIO) instance Monoid a => Monoid (Query a) where mempty = return mempty mappend = liftM2 mappend So 'mappend' for Query is just the 'mappend' for Endo, lifted over the ReaderT. But of course, 'mappend' for Endo is just function composition. The upshot is that m1 <+> m2 does m2, and THEN m1. Mostly no one notices since ManageHooks tend to consist of a bunch of actions with disjoint premises, so it doesn't matter in which order they are run. But this order is quite counterintuitive when trying to sequence multiple actions in a ManageHook (as someone was just trying to do in #xmonad today, which is how I ran across this issue). I propose to change the Monoid instance for Query so that mappend = liftM2 (flip mappend) Of course, this has the undesirable side effect of breaking any configs where the order actually matters. But it would certainly make more sense moving forward, IMO. Thoughts? -Brent

Brent Yorgey
The upshot is that m1 <+> m2 does m2, and THEN m1.... I propose to change the Monoid instance for Query so that mappend = liftM2 (flip mappend)
When m2 is done followed by m1, sometimes the effect of m1 "takes precedence" (for example, when "doFloat" is pitted against "unfloat = ask >>= \w -> doF (W.sink w)") but sometimes the effect of m2 "takes precedence". I have had to reason about what takes precedence, and this proposed change would make the reasoning harder for me, simply because "flip" is one more level of indirection and I am already used to the match between "mappend" and the mathematical convention for function composition. So, I would say that the proposed change should be made iff this new meaning of <+> can be documented clearly and predictably without reference to the Endo Monoid notion of function composition. -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig We want our revolution, and we want it now! -- Marat/Sade We want our revolution, and we'll take it at such time as you've gotten around to delivering it -- Haskell programmer

On Tue, Jun 09, 2009 at 07:42:58PM -0400, Chung-chieh Shan wrote:
Brent Yorgey
wrote in article <20090609164904.GA5859@seas.upenn.edu> in gmane.comp.lang.haskell.xmonad: The upshot is that m1 <+> m2 does m2, and THEN m1.... I propose to change the Monoid instance for Query so that mappend = liftM2 (flip mappend)
When m2 is done followed by m1, sometimes the effect of m1 "takes precedence" (for example, when "doFloat" is pitted against "unfloat = ask >>= \w -> doF (W.sink w)") but sometimes the effect of m2 "takes precedence". I have had to reason about what takes precedence, and this proposed change would make the reasoning harder for me, simply because "flip" is one more level of indirection and I am already used to the match between "mappend" and the mathematical convention for function composition. So, I would say that the proposed change should be made iff this new meaning of <+> can be documented clearly and predictably without reference to the Endo Monoid notion of function composition.
Hmm. I can see how that would be confusing. I suppose another solution would be to just add another combinator which is like <+> but flipped, with some clear documentation. Actually, just adding some clearer documentation would probably go a long way without even changing any code. -Brent

* On Tuesday, June 09 2009, Brent Yorgey wrote: [...]
I propose to change the Monoid instance for Query so that
mappend = liftM2 (flip mappend)
Of course, this has the undesirable side effect of breaking any configs where the order actually matters. But it would certainly make more sense moving forward, IMO.
I saw this too when writing XMonad.Hooks.InsertPosition in contrib. It would be nicer to reflect the change in the type: type ManageHook = Query (Dual (Endo WindowSet)) But unfortunately, this requires some simple changes to contrib: s/Endo/(Dual . Endo)/ should do. Some configs may break too. Adam
participants (3)
-
Adam Vogt
-
Brent Yorgey
-
Chung-chieh Shan