Some clarity please! (was Re: [Haskell-cafe] Re: (flawed?) benchmark : sort)

2008-03-13 Thread Adrian Hey
 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)

2007-05-24 Thread Adrian Hey

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

2007-05-24 Thread Adrian Hey

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

2007-05-23 Thread Adrian Hey

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)

2007-05-23 Thread Adrian Hey

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

2007-05-20 Thread Adrian Hey

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

2007-03-19 Thread Adrian Hey

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