Some clarity please! (was Re: [Haskell-cafe] Re: (flawed?) benchmark : sort)
wouldn't dispute that the default definition is reasonable, but it's certainly not clear to me from the report that it's something that I can safely assume for all Ord instances. In fact AFAICS the report quite clearly telling me *not* to assume this. But I have to assume *something* for maximum to make sense, so I guess that must be: (x==y) = True implies x=y IOW I have no idea if it's the first or last maximum that is returned, but who cares? Again, the report doesn't make it clear that the (==) law above holds (at least not on page 82). But I think in the absence of any explicit statement to the contary I think most programmers would assume that it does apply. I think this is quite reasonable and I have no intention of changing my programming habits to cope with weird instances for which: (x == y) = True does not imply x=y or max x y is not safely interchangeble with max y x. I'm not saying some people are not right to want classes with more mathematically inspired laws, but I see nothing in the report to indicate to me that Eq/Ord are those classes and consequently that the naive programmers interpretation of (==) is incorrect. Rather the contrary in fact. Regards -- Adrian Hey Aaron Denney wrote: On 2008-03-12, Adrian Hey [EMAIL PROTECTED] wrote: Aaron Denney wrote: On 2008-03-11, Adrian Hey [EMAIL PROTECTED] wrote: Having tried this approach myself too (with the clone) I can confirm that *this way lies madness*, so in future I will not be making any effort to define or respect sane, unambiguous and stable behaviour for insane Eq/Ord instances for any lib I produce or hack on. Instead I will be aiming for correctness and optimal efficiency on the assumption that Eq and Ord instances are sensible. Good. But sensible only means that the Eq and Ord instances agree, not that x == y = f x == f y. So can I assume that max x y = max y x? No. You can, however, assume that max x y == max y x. (Okay, this fails on Doubles, because of NaN. I'll agree that the Eq and Ord instances for Double are not sane.) If not, how can I tell if I've made the correct choice of argument order. When calling, or when defining max? It depends on what types you're using, and which equivalence and ordering relations are being used. When calling, and when it might matter which representative of an equivalence class comes back out (such as in sorts) you have no choice but to look at the documentation or implementation of max. The Haskell report guarantees that x == y = max x y = y (and hence max y x = x), and the opposite choice for min. This is to ensure that (min x y, max x y) = (x,y) or (y,x). IOW, the report notices that choice of representatives for equivalence classes matters in some circumstances, and makes it easy to do the right thing. This supports the reading that Eq a is not an absolute equality relation, but an equivalence relation. If I can't tell then I guess I have no alternative but document my arbitrary choice in the Haddock, and probably for the (sake of completeness) provide 2 or more alternative definitions of the same function which use a different argument order. When defining max, yes, you must take care to make sure it useable for cases when Eq is an equivalence relation, rather than equality. If you're writing library code, then it won't generally know whether Eq means true equality rather than equivalence. If this would let you optimize things, you need some other way to communicate this. The common typeclasses are for generic, parameterizable polymorphism. Equivalence is a more generally useful notion than equality, so that's what I want captured by the Eq typeclass. And no, an overloaded sort doesn't belong in Ord, either. If the implementation is truly dependent on the types in non-trivial, non-susbstitutable ways (i.e. beyond a substition of what = means), then they should be /different/ algorithms. It would be possible to right an Equal a typeclass, which does guarantee actual observable equality (but has no methods). Then you can write one equalSort (or whatever) of type equalSort :: (Eq a, Ord a, Equal a) = [a] - [a] that will work on any type willing to guarantee this, but rightly fail on types that only define an equivalence relation. A stable sort is more generally useful than an unstable one. It's composable for radix sorting on compound structures, etc. Hence we want to keep this guarantee. ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Suggestion for module system (to get rid of many uses of unsafePerformIO)
Stephen Dolan wrote: At the moment, we have the situation of modules using unsafePerformIO newIORef, which influences program behaviour without being referenced by main. Not really. Even with things as they currently are, if we have at the top level.. resultOfSomething = unsafePerformIO doSomething .. laziness will ensure that nothing will happen unless the value resultOfSomething is demanded (by main ultimately). Of course, this does not imply the above hack is at all safe. Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: [Haskell-cafe] global variables
Taral wrote: On 5/23/07, Adrian Hey [EMAIL PROTECTED] wrote: I think I still prefer.. var :: IORef Int var - newIORef 3 So do I. For one very good reason: this syntax could be defined as a constructor syntax and guaranteed to run before main. Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). But anyway, the constraints of the ACIO monad allow creation to occur at any time before the first attempt to read or write the IORef. The other syntaxes proposed don't strike me as sufficiently rigorous. Me neither. It's always been a great source of puzzlement to me why this very simple and IMO conservative proposal should be so controversial. Unless someone can point out some severe semantic difficulty or suggest something better it seems like a no-brainer to me. Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: [Haskell-cafe] global variables
Isaac Dupree wrote: var :: IORef Int var = {-# EVALUATE_THIS_TEXT_ONLY_ONCE #-} (unsafePerformIO (newIORef 3)) I think I still prefer.. var :: IORef Int var - newIORef 3 or, more likely.. var :: IORef Int var - ACIO.newIORef 3 The - syntax should make the intended semantics clear and unambiguous, so it becomes the problem of individual implementors (not standards writers) to make sure that whatever optimisations or transformations that may be appropriate for their implementation preserve those semantics. (IOW there's no need to worry about what a pragma really means in operational terms, AFAICS). The ACIO monad also restricts what programmers may use on the rhs of the -. But if you want a good name for the pragma how about this.. var :: IORef Int var = {-# - #-} (unsafePerformIO (newIORef 3)) :-) Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: Suggestion for module system (to get rid of many uses of unsafePerformIO)
Stephen Dolan wrote: Would this be useful, useless, or just downright silly? The silence is deafening :-) I think what you're describing seems to be so completely different from Haskell as it is now that that people either don't understand it, or they do understand it and do think it's downright silly, but are just too polite to say that. Maybe you should try writing it up in a more comprehensible form on a Haskell wiki page. I would say that I get worried when people talk about module initialisation and/or (potentially) side effecting imports. I'm not sure if this is a problem with what you're proposing, but I think it's important that we don't get into a situation where the mere presence or absence of some definition in a module can influence program behaviour, even if it isn't referenced by main somehow. Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: [Haskell-cafe] global variables
Isaac Dupree wrote: Maybe some sort of ISOLATE, DON'T_OPTIMIZE (but CAF), or USED_AS_GLOBAL_VARIABLE pragma instead of just the insufficient NOINLINE would be a good first step... if successful it would remove the occasional need for -fno-cse for a whole module in GHC, at least. I have a hard time trying to understand why anyone would prefer this to the simple and clear - syntax that's been proposed. As for the ACIO monad itself, this is utterly trivial and requires no language change. It's just a library. Maybe the first pragma you propose might have other uses to control optimisations, so I'm not totally anti this. But generally I dislike pragmas (I always find myself wondering what's wrong with the language design that makes the pragma necessary). So pragmas that influence optimisation are something I can live with. But using pragmas to influence *semantics* really is an evil practice IMO and is something that should be discouraged, not made an unavoidable necessity. But yes, if this problem isn't going to be properly addressed then at the very least the -fno-cse flag or something similar needs standardising (NOINLINE already is I think). Or we port all existing unsafePerfomIO hacked code to use Johm Meachams variant of the hack (uses types to ensure the compiler doesn't see common sub-expressions). Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
Re: strict bits of datatypes
Simon Peyton-Jones wrote: | strict fields have no effect on deconstructing data types. That's GHC's behaviour too. I think it's the right one too! (It's certainly easy to explain.) This reminds me of something I discovered about using strict fields in AVL trees (with ghc). Using strict fields results in slower code than doing the `seq` desugaring by hand. If I have.. data AVL e = E | N !(AVL e) e !(AVL e) .. etc then presumably this.. case avl of N l e r - N (f l) e r desugars to something like .. case avl of N l e r - let l' = f l in l' `seq` r `seq` N l' e r but IMO it should desugar to.. case avl of N l e r - let l' = f l in l' `seq` N l' e r which is what I ended up writing by hand all over the place (dropping the strictness annotation in the data type). That is, variables that have been obtained by matching strict fields (r in the case) should not be re-seqed if they are re-used in another strict context. Now this explanation for the slow down I observed is just speculation on my part (I don't actually know what ghc or any other compiler does). But on modern memory architectures, forcing the code to inspect heap records that it shouldn't have to inspect will be a bad thing. So semantically I agree with strict fields have no effect on deconstructing data types, but they should have an effect on the code that an optimising compiler generates IMO. Regards -- Adrian Hey ___ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime