On 27 Jan 2010, at 16:33, Jan-Willem Maessen wrote:

I'm not sure why you want to throw in functions between maps in the two first arguments. Then there is no requirement that single keys are preserved.

But it is a good idea to have a Maybe so that one can remove keys on the fly.

A good point. Technically, one should delimit the scope of the first two arguments:

data KeyPreservingMapOperation k a b = AlwaysEmpty | Identity | MapMaybeWithKey (k -> a -> Maybe b)

perform :: KeyPreservingMapOperation a b -> Map k a -> Map k b
perform AlwaysEmpty = const empty
perform Identity = id
perform (MapMaybeWithKey f) = mapMaybeWithKey f

I'm thinking about
  (k -> Maybe a -> Maybe b -> Maybe c) -> Map k a -> Map k b -> Map k c
The first two Maybe's tell if the keys are present, the last if one wants it in the resulting map.

When throwing together tree-like data structures, I often start by writing this function; it handles most of the bulk operations I might want to do as one-liners. It's got a messy, ugly type signature, but it does everything you want as efficiently as you want.*

My guess is that is when you write things from scratch.

Yes. On the other hand, I've repeatedly run into the same problem you're describing: a api that doesn't give me an efficient way to perform an operation I know to be very simple. If every map provided an operation like this one, then I can avoid writing my own library "from scratch" when I need it --- especially when "from scratch" means "fork the code and add what I need".

So, library implementors: think hard about your "swiss army knife" combinators. You end up with messy functions with gigantic signatures. On the other hand, you can often add a couple of judicious INLINE annotations and remove tons of code from the rest of your library. Then expose them, and mark them as the functions of last resort that they truly are.

One can transverse the product of keys. Then I'm thinking about
(k1 -> k2 -> a -> b -> Maybe c -> Maybe(k, c)) -> Map k1 a -> Map k2 b -> Map k c The first Maybe tells if the key is already present; the second if one wants it inserted.

The idea in both cases is to combine the modifying functions into one. This simplifies the interface.

  Hans


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to