
Now, in the case where equality from Ord key is an equivalence rather than true equality, I can see that using "new_key" in the otherwise case is the right thing to do.
For my case, it means that the recently allocated new_key replaces the old key that will have been around longer. Doesn't this interact badly with generational collectors?
Is this causing you real grief? If it is, as you say, the Right Thing To Do, then can we really change it?
Oh yes, and since the similar operations on Refs and states are called modifyBlah, shouldn't the _C versions of operations on FiniteMaps be called something with "modify" in them?
so addToFM_C would become modifyFM addListToFM_C ----"--- listModifyFM
etc. I think names with words rather than abbreviations are easier to read when returning to something after a long period of absence.
I agree, and if I had my way we would remove all the 'FM' suffices too. But name changes shouldn't be made gratuitously; FiniteMap is one of the more heavily-used modules in the libraries (certainly by me, and I expect other people too). I suppose we could rename everything exported by the library, leaving the old names in place for a couple of versions (deprecated, of course). Would someone like to suggest a complete new interface? Cheers, Simon

... and if I had my way we would remove all the 'FM' suffices too.
yes yes yes yes. both `FiniteMap.empty' and `empty :: FiniteMap Foo Bar' look infinitely better than `emptyFM'. oops, the second example doesn't actually work (if another `empty' is in scope) since we don't have static overloading. best regards, -- -- Johannes Waldmann ---- http://www.informatik.uni-leipzig.de/~joe/ -- -- joe@informatik.uni-leipzig.de -- phone/fax (+49) 341 9732 204/252 --

... and if I had my way we would remove all the 'FM' suffices too. yes yes yes yes.
both `FiniteMap.empty' and `empty :: FiniteMap Foo Bar' look infinitely better than `emptyFM'.
A problem with relying on qualified import in this way is that it is hard to build aggregate interfaces (a module that imports half a dozen other modules and reexports them unchanged). The HGL used to use qualified import (for all those 'create a Foo, select a Foo in current graphics context, delete a Foo' functions) but we switched back to a more traditional interface because we couldn't build aggregate interfaces. So, while I agree that it looks nicer, it's not necessarily better. Anyway, isn't there some kind of collection class that FM can be made a member of? -- Alastair Reid

Alastair Reid
Anyway, isn't there some kind of collection class that FM can be made a member of?
Curiously, it seems classes aren't used much in the libraries. I.e. I wanted my data structure to be used more or less like an array (it was basically an array with some extras), but I couldn't just instance Indexed Foo where a ! i = ... bounds a = ... I can of course always define operations using different names, but IMHO reusing common ones, like (!) makes the code much more readable. Similar for Sets, lists, and FMs, I'd expect something like instance Collection a where empty = ... (!!) cardinality -- or whatever and so on. It is quite possible that there are technical difficulties defining good, generic classes like this, and that I haven't looked deeply enough into the matter -- I vaguely remember a posting from Chris Okasaki about classes in the Edison library regarding this. OTOH, I find I define classes very sparingly in my own programming. Comong from an OO world I started out with a desire to create classes for just about anything, but in practice, it rarely seems necessary. So while it still can be useful or desirable, it just doesn't get done. -kzm -- If I haven't seen further, it is by standing in the footprints of giants

Similar for Sets, lists, and FMs, I'd expect something like
instance Collection a where empty = ... (!!) cardinality -- or whatever
There is also the option of separating things even further, like class Size a where size :: a -> Int class Empty a where empty :: a ultimately each function is the (single) method of a class. for accessing an indexed collection , write class Bang c where (!!) : c a b -> a -> b (this is AssocX.lookup in Edison, http://www.haskell.org/ghc/docs/edison/users008.html#toc35) even better, since this is actually a (partial) mapping, change (!!) to ($), and we have unified notation for functions, arrays, lists, finite maps... not entirely joking, -- -- Johannes Waldmann ---- http://www.informatik.uni-leipzig.de/~joe/ -- -- joe@informatik.uni-leipzig.de -- phone/fax (+49) 341 9732 204/252 --

Hi all, On 19 Jun 2002, Ketil Z. Malde wrote:
Alastair Reid
writes: OTOH, I find I define classes very sparingly in my own programming. Comong from an OO world I started out with a desire to create classes for just about anything, but in practice, it rarely seems necessary. So while it still can be useful or desirable, it just doesn't get done.
There are always (as I see it) three options: - Use a class -- i.e., Set s a => empty :: s a - Use a "qualified" name -- i.e., S.empty :: Set a - Use a name with a qualifier tacked on manually -- i.e., emptySet :: Set a Going from the bottom up, we have the least complex up to the most complex. The qualified name option has as a problem (pointed out recently, I don't remember whom by) the issue of collection modules. I think the general policy I've used is: if there is already a class into which it fits, put it in a class; otherwise, put use the third option. This is largely due to the fact that the Prelude was so well designed. Usually, whatever my data type, the operations I wish to perform over it fall into some function from the prelude, most usually: map, fold, filter (though less often filter than the other two), mapAccum, mapM, foldM, lookup, find, and maybe a few otheres (For instance, I wrote all of these functions to work on top of the HsSyn library of Haskell syntax to easy some work I was doing.) The problem is that the prelude is so well put together than I rarely need more functions than it provides for my datatypes (at least, more *general* functions; obviously each data type has data-specific functions, but I'm glossing over that now). The problem this leaves me with is that it's taken all the good names. So I end up calling the functions on my trees: tmap, tfold, tlookup, etc... (Though occasionally I use fmap in Functor instead of tmap.) This extends beyond collections; I recently needed a datatype (silly as it may sound), which is |R U {+oo, -oo}, with addition defined as: -oo + _ = -oo oo + _ = oo r + r = r + r (obviously associative). That is, -oo always wins out, even over +oo, but otherwise it's just "normal" addition. The problem is, I either had to use some strange symbol like $+ for addition, or make it an instance of Num, without any of the other operations (I opted for the latter). I've been considering both (a) using Ashley's prelude, which seems to adopt a one-op-per-class mentality or (b) learning more about Clean. I know there was some talk a while back about having a "beginners" prelude (similar to what we have now) and an "advanced" prelude, supposedly similar to Ashley's. I would definately be in favor of this. Whether we call it class Add or class Group is largely irrelevant to me (I tend to find class names to be fairly superfluous anyway). I think the only classes I ever write (or derive) instances of are: Eq, Ord, Show, Read (rarely), Num, Binary, Fractional (rarely), Hash, DeepSeq, Monad (rarely), Functor (rarely) Okay, well I guess that's almost all of them. But according to a quick grep, the only onces I write frequently are: Eq, Ord, Show, Num Moreover, the only *classes* I've ever defined (other than for toy little tests with classes) are: Hashable, Container Though the functions I frequently want to override (listed above) fall into none of these. So...yeah...I've kind of lost my train of thought, but I think that the problem I've frequently had is that I want to use the names the prelude uses, but can't. :). That's all. - Hal

So...yeah...I've kind of lost my train of thought, but I think that the problem I've frequently had is that I want to use the names the prelude uses, but can't. :).
Back when Haskell 1.4 (or 98?) was being designed, I proposed that Haskell's rule that the Prelude is implicitly imported into every module should be dropped. Benefit: simpler language, easier to replace Prelude with your own. Cost: requires you to type 2 extra tokens in every module and to ask students to type it in without first giving them a full explanation of what it means. Didn't get anywhere. I'm wondering if that would help at all? [Possibly not. When I worked on Yale Haskell (which was written in Lisp), I cursed and swore at the Lisp hackers who seemed to have defined their own personal subset of Lisp in which every symbol meant something slightly different from what it meant in any one Lisp. That is, one of Haskell's goals was to create a common language for all lazy language research so it might be a mistake to make fragmentation easy.] -- Alastair

Yes, I agree with your [Possibly not...] statement, which I why I think I'm in favor of having the "two Preludes" option, but having both standard (this is part of my reason for not adopting Ashley's Prelude). I think a reasonable way to do it would be to have module AdvancedPrelude which defines the map, fold, etc functions all in their own class, something like: class Map m a where map :: (a -> b) -> m a -> m b mapAccum :: ... and so on. It also defines things like Group, Ring, etc. The standard Prelude then imports the Advanced prelude, hiding all the map classes and imports the Group and Ring but doesn't export them; instead it wraps them into Num, etc., as we have now. It also defines the map, etc. functions over lists as we normally do. You then can either import neither, in which case you get the Prelude, explicitly import AdvancedPrelude, in which case you get the Advanced prelude but not the Prelude, import both (in which case you're screwed). The "importing AdvancedPrelude => no import Prelude" may rub some folks the wrong way, but it's really only marginally different from the (imo strange) rules regarding how importing the prelude works today...if you don't import it, you get it, or if you import it hiding things, that cancels out the automatic import, etc... I don't know if such a thing is possible, but it would be nice to have a standard but more advnaced prelude. -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On 19 Jun 2002, Alastair Reid wrote:
So...yeah...I've kind of lost my train of thought, but I think that the problem I've frequently had is that I want to use the names the prelude uses, but can't. :).
Back when Haskell 1.4 (or 98?) was being designed, I proposed that Haskell's rule that the Prelude is implicitly imported into every module should be dropped. Benefit: simpler language, easier to replace Prelude with your own. Cost: requires you to type 2 extra tokens in every module and to ask students to type it in without first giving them a full explanation of what it means. Didn't get anywhere.
I'm wondering if that would help at all?
[Possibly not. When I worked on Yale Haskell (which was written in Lisp), I cursed and swore at the Lisp hackers who seemed to have defined their own personal subset of Lisp in which every symbol meant something slightly different from what it meant in any one Lisp. That is, one of Haskell's goals was to create a common language for all lazy language research so it might be a mistake to make fragmentation easy.]
-- Alastair
participants (5)
-
Alastair Reid
-
Hal Daume III
-
Johannes Waldmann
-
ketil@ii.uib.no
-
Simon Marlow