Re: Superclass defaults

2011-09-05 Thread Jonas Almström Duregård
 What sayeth ye all?

I approve of your suggestion. Well said!

 3. I must admit I don't fully see how client code can be kept from the need
 to enable the extension. In particular, if client code must use the explicit
 opt-out, this is a rather obvious syntactic change - are you really
 suggesting that we enable new syntax without the need to declare what
 language (i.e. extensions) the file uses?

I can only speak for myself, but I believe the intention was never to
allow the syntactic changes without a flag. The only part that I
understood to be be flag-less is exactly the extension you call
SilentDefaultSuperInstances.

Now about the names...

I suggest IntrinsicInstanceDeclarations for the auto-enabled
extension, and just IntrinsicSuperclasses for the larger extension.

Regards,
Jonas


On 3 September 2011 12:21, Niklas Broberg niklas.brob...@gmail.com wrote:
 On Mon, Aug 22, 2011 at 10:05 AM, Max Bolingbroke
 batterseapo...@hotmail.com wrote:

 On 21 August 2011 21:03, Alexey Khudyakov alexey.sklad...@gmail.com
 wrote:
  I don't completely understant how does it work. Does client need to
  enable
  language extension to get default instances?

 I think that the extension would only be required to *define them*,
 not for them to be generated. The more conservative choice would
 indeed be to require the extension for both, though.

 Please allow me to voice my not-so-humble opinion that, as a rigid
 principle, any extension is ALWAYS enabled with a flag, and never enabled
 silently. This is what Max calls the conservative choice, while I would
 like to call it the only sensible choice.
 1. In particular: adhering to this principle makes it much much easier to
 achieve consistency between different compilers and tools working with
 Haskell code. GHC is currently in so strong a position as to make its own
 laws, but with great power comes great responsibility. Even if GHC will
 always have the proper context available, it is by no means certain that
 other tools will. In this particular instance, it is certainly not
 inconceivable or even improbable that tools other than compilers might want
 to analyse a module containing instance declarations, without knowing a
 priori that some default superclass instances are assumed. Having a flag
 always makes this clear.
 (As an example, GHC already breaks this principle in (at least) one instance
 - MPTC when used as contexts - which creates problems for haskell-src-exts).

 2. If you are worried about breakage of legacy code, you can always achieve
 silent enabling by having a flag and having it on by default. Then GHC can
 declare that it, by default, compiles a Haskell extension and not the
 standard. This could still create problems when programmers expect other
 tools to work on their GHC-specific files, but then at least we have a clear
 story and can put blame where blame is due (on GHC). Other tools can then
 also opt to enable the same extensions by default, or by flag. Also, it
 would make it possible to explicitly remove the flag in client code (with
 the appropriate -XNo... flag).
 From a principle point of view this is still not a perfect solution, and I
 would prefer that an explicit flag was always needed (unless and until the
 extension is adopted in the proper Haskell' revision). I realise this would
 break a lot of code though, and having a flag enabled by default is far, far
 better than not using a flag at all.
 3. I must admit I don't fully see how client code can be kept from the need
 to enable the extension. In particular, if client code must use the explicit
 opt-out, this is a rather obvious syntactic change - are you really
 suggesting that we enable new syntax without the need to declare what
 language (i.e. extensions) the file uses? Of course, there is precedent for
 such a move with the ugly MPTCs-in-contexts mentioned above - a precedent
 that I would very much like to see revoked. I would in any case like to
 voice my very strong opinion against such a choice.

 That said - I definitely like the general idea of default superclass
 instances, I think the proposed extension is very elegant and fixes a
 definite wart. But please let's not introduce other problems by adopting it!
 To be concrete, I propose the following named extensions (exact names up for
 bike-shed discussion):
 * DefaultSuperInstances: Enables the full SHE-bang (pun fully intended),
 including in particular the syntactic additions in class and instance
 declarations.
 * SilentDefaultSuperInstances: Enables ONLY the possibility for client code
 to use inherited default instances. This extension is subsumed by
 DefaultSuperInstances (except for error/warning behavior discussed below),
 just like RankNTypes subsumes Rank2Types.
 I further propose that GHC enables SilentDefaultSuperInstances by default,
 as a pragmatic choice to avoid legacy issues, but not DefaultSuperInstances.
 If (only) SilentDefaultSuperInstances is enabled, I propose that Option 2 is
 used. It 

Re: Superclass defaults

2011-09-03 Thread Niklas Broberg
On Mon, Aug 22, 2011 at 10:05 AM, Max Bolingbroke 
batterseapo...@hotmail.com wrote:

 On 21 August 2011 21:03, Alexey Khudyakov alexey.sklad...@gmail.com
 wrote:
  I don't completely understant how does it work. Does client need to
 enable
  language extension to get default instances?

 I think that the extension would only be required to *define them*,
 not for them to be generated. The more conservative choice would
 indeed be to require the extension for both, though.


Please allow me to voice my not-so-humble opinion that, as a rigid
principle, any extension is ALWAYS enabled with a flag, and never enabled
silently. This is what Max calls the conservative choice, while I would
like to call it the only sensible choice.

1. In particular: adhering to this principle makes it much much easier to
achieve consistency between different compilers and tools working with
Haskell code. GHC is currently in so strong a position as to make its own
laws, but with great power comes great responsibility. Even if GHC will
always have the proper context available, it is by no means certain that
other tools will. In this particular instance, it is certainly not
inconceivable or even improbable that tools other than compilers might want
to analyse a module containing instance declarations, without knowing a
priori that some default superclass instances are assumed. Having a flag
always makes this clear.

(As an example, GHC already breaks this principle in (at least) one instance
- MPTC when used as contexts - which creates problems for haskell-src-exts).


2. If you are worried about breakage of legacy code, you can always achieve
silent enabling by having a flag and having it on by default. Then GHC can
declare that it, by default, compiles a Haskell extension and not the
standard. This could still create problems when programmers expect other
tools to work on their GHC-specific files, but then at least we have a clear
story and can put blame where blame is due (on GHC). Other tools can then
also opt to enable the same extensions by default, or by flag. Also, it
would make it possible to explicitly remove the flag in client code (with
the appropriate -XNo... flag).

From a principle point of view this is still not a perfect solution, and I
would prefer that an explicit flag was always needed (unless and until the
extension is adopted in the proper Haskell' revision). I realise this would
break a lot of code though, and having a flag enabled by default is far, far
better than not using a flag at all.

3. I must admit I don't fully see how client code can be kept from the need
to enable the extension. In particular, if client code must use the explicit
opt-out, this is a rather obvious syntactic change - are you really
suggesting that we enable new syntax without the need to declare what
language (i.e. extensions) the file uses? Of course, there is precedent for
such a move with the ugly MPTCs-in-contexts mentioned above - a precedent
that I would very much like to see revoked. I would in any case like to
voice my very strong opinion against such a choice.


That said - I definitely like the general idea of default superclass
instances, I think the proposed extension is very elegant and fixes a
definite wart. But please let's not introduce other problems by adopting it!

To be concrete, I propose the following named extensions (exact names up for
bike-shed discussion):

* DefaultSuperInstances: Enables the full SHE-bang (pun fully intended),
including in particular the syntactic additions in class and instance
declarations.
* SilentDefaultSuperInstances: Enables ONLY the possibility for client code
to use inherited default instances. This extension is subsumed by
DefaultSuperInstances (except for error/warning behavior discussed below),
just like RankNTypes subsumes Rank2Types.

I further propose that GHC enables SilentDefaultSuperInstances by default,
as a pragmatic choice to avoid legacy issues, but not DefaultSuperInstances.


If (only) SilentDefaultSuperInstances is enabled, I propose that Option 2 is
used. It makes perfect sense to warn if you override a default instance,
just like it is sensible to warn about name shadowing. Option 3 strikes me
as strictly worse. However, if DefaultSuperInstances is enabled (which must
then be done explicitly), I propose that Option 1 is used instead.


2011/9/2 Conor McBride co...@strictlypositive.org

 On 2 Sep 2011, at 18:19, Jonas Almström Duregård wrote:

The recent discussion concerns whether option 2 should eventually be
 shifted to option 1. Everyone seems to agree that option 2 should be
 used initially.


With my proposal this discussion becomes moot. SilentDefaultSuperInstances
effects option 2, DefaultSuperInstances effects option 1. The discussion can
then instead turn to whether or not DefaultSuperInstances should be adopted
in Haskell', and (only) at that point there will be an automatic switch to
option 1.

A similar warning should perhaps indicate that a hiding 

Re: Superclass defaults

2011-09-02 Thread Jonas Almström Duregård
Hi,

On 31 August 2011 12:22, Conor McBride co...@strictlypositive.org wrote:
 I become perplexed very easily. I think we should warn whenever silent
 pre-emption (rather than explicit) hiding is used to suppress a default
 instance, because it is bad --- it makes the meaning of an instance
 declaration rather more context dependent. Perhaps a design principle
 should be that to understand an instance declaration, you need only
 know (in addition) the tower of class declaration s above it: it is
 subtle and worrying to make the meaning of one instance declaration
 depend on the presence or absence of others.

Those are all good arguments, and you've convinced me that always
warning is better.

 Arguably, option 1 does not conflict with design goal 1. Design goal 1
 supports a methodology for refining a class into a hierarchy without
 creating the need for stacks of default instances or breaking code. If
 the new superclass is a brand new thing without legacy instances,
 there's no problem. If we'd had this mechanism in place, Functor would
 always have been made a superclass of Monad, Applicative would have
 been easily inserted, and we wouldn't have the stacks of manually added
 default instances to worry about.

 The main problem with Option 1 is in dealing with the legacy of
 classes which currently require a stack of default instances, creating
 a hierarchy from parts which already exist. Option 1 would create a bunch
 of instance conflicts and thus demand changes to code. Design goal 1
 isn't very explicit (sorry!) about this distinction between introducing
 new classes as superclasses and building hierarchies from legacy classes,
 but it was the former I intended. I always expected the latter to cause
 trouble.

 If it is also a design goal to minimize damage with respect to the
 current unfortunate situation, then Option 1 is problematic. Whatever we
 might wish, we are where we are. We should be pragmatic. I think we
 should set Option 1 as the direction of travel, but go with Option 2 for
 the moment. We should make sure that the warnings generated by Option 2
 are sufficiently informative that it is easy to track down the conflicts
 and resolve them explicitly, for Option 1 compliance.

First of all, I think the design goal is quite clear: a class C can
be re-factored into a class C with a superclass S, without disturbing
any clients. Requiring client C to opt-out from the default
implementation of S is a clear violation of the design goal. So I
disagree that option 1 can be compatible with the design goal, but
like you say the design goal might be at fault.

Also, if I understand you correctly, you say the current situation is
exceptional, and suggest option 2 as a temporary solution to it. You
seem convinced that these kind of situations will not appear in the
future, but I'm not as optimistic about that.

Even when superclass defaults are implemented, people will
occasionally implement classes without realizing that there is a
suitable intrinsic superclass (or add the superclass but not the
default instance). People will start using the new class and give
separate instances for the superclass, and eventually someone will
point out that the there should be a default instance for the
superclass. Now if option 1 is implemented, the library maintainers
will be reluctant to add the superclass instance because it will break
a lot of client code.

Will there be a solution to this dilemma that I have missed? Should
the client code be allowed opt-out from the superclass preemptively
before it is given a default? Won't that cause a similar perplexity?

Regards,
Jonas

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Conor McBride

Hi

On 2 Sep 2011, at 10:55, Jonas Almström Duregård wrote:
On 31 August 2011 12:22, Conor McBride co...@strictlypositive.org  
wrote:
I become perplexed very easily. I think we should warn whenever  
silent
pre-emption (rather than explicit) hiding is used to suppress a  
default

instance, because it is bad --- it makes the meaning of an instance
declaration rather more context dependent. Perhaps a design principle
should be that to understand an instance declaration, you need only
know (in addition) the tower of class declaration s above it: it is
subtle and worrying to make the meaning of one instance declaration
depend on the presence or absence of others.


Those are all good arguments, and you've convinced me that always
warning is better.


The question then comes down to whether that warning should ever be
strengthened to an error.


First of all, I think the design goal is quite clear: a class C can
be re-factored into a class C with a superclass S, without disturbing
any clients. Requiring client C to opt-out from the default
implementation of S is a clear violation of the design goal. So I
disagree that option 1 can be compatible with the design goal, but
like you say the design goal might be at fault.


Design goal 1 does not explicitly distinguish the scenarios where S
is pre-existing or being introduced afresh. If the former, it's
inaccurate to describe what's happening as refactoring C, for S is
experiencing some fall-out, too. We should clearly seek more precision,
one way or another.


Also, if I understand you correctly, you say the current situation is
exceptional, and suggest option 2 as a temporary solution to it. You
seem convinced that these kind of situations will not appear in the
future, but I'm not as optimistic about that.

Even when superclass defaults are implemented, people will
occasionally implement classes without realizing that there is a
suitable intrinsic superclass (or add the superclass but not the
default instance). People will start using the new class and give
separate instances for the superclass, and eventually someone will
point out that the there should be a default instance for the
superclass. Now if option 1 is implemented, the library maintainers
will be reluctant to add the superclass instance because it will break
a lot of client code.


I agree that such a scenario is possible. The present situation gives
no choice but to do things badly, but things often get done badly the
first time around anyway. Perhaps I'm just grumpy, but I think we
should aim to make bad practice erroneous where practicable. Once
the mistake is no longer forced upon us, it becomes a mistake that
deserves its penalty in labour. Silent pre-emption is bad practice and
code which relies on it should be fixed: it's not good to misconstrue
an instance declaration because you don't know which instance
declarations are somewhere else. Nonmonotonic reasoning is always a
bit scary.

From a library design perspective, we should certainly try to get these
hierarchical choices right when we add classes. I accept that it should
be cheap to fix mistakes (especially when the mistake is lack of
foresight. Sticking with the warning rather than the error reduces the
price of this particular legacy fix at the cost of tolerating misleading
code. I agree that the balance of this trade-off is with the warning,
for the moment, but I expect it to shift over time towards the error.
But if it's clear what the issue is, then we can at least keep it under
review.


Will there be a solution to this dilemma that I have missed? Should
the client code be allowed opt-out from the superclass preemptively
before it is given a default? Won't that cause a similar perplexity?


I don't know what you mean by this. Perhaps you could expand on it?

All the best

Conor


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Brandon Allbery
I hope I am misunderstanding this

2011/9/2 Conor McBride co...@strictlypositive.org

 Also, if I understand you correctly, you say the current situation is
 exceptional, and suggest option 2 as a temporary solution to it. You
 seem convinced that these kind of situations will not appear in the
 future, but I'm not as optimistic about that.

 Even when superclass defaults are implemented, people will
 occasionally implement classes without realizing that there is a
 suitable intrinsic superclass (or add the superclass but not the
 default instance). People will start using the new class and give
 separate instances for the superclass, and eventually someone will
 point out that the there should be a default instance for the
 superclass. Now if option 1 is implemented, the library maintainers
 will be reluctant to add the superclass instance because it will break
 a lot of client code.


 I agree that such a scenario is possible. The present situation gives
 no choice but to do things badly, but things often get done badly the
 first time around anyway. Perhaps I'm just grumpy, but I think we
 should aim to make bad practice erroneous where practicable. Once
 the mistake is no longer forced upon us, it becomes a mistake that
 deserves its penalty in labour. Silent pre-emption is bad practice and


So, when the whole point is that an unfortunate design years ago can't be
reasonably fixed without rewriting massive amounts of code, the only correct
answer is to rewrite massive amounts of code?  Especially when the original
proposal was put forward *specifically to avoid* rewriting massive amounts
of code?

Yes,  we'd love a perfect world.  We don't have one.  That's the *point*.

-- 
brandon s allbery  allber...@gmail.com
wandering unix systems administrator (available) (412) 475-9364 vm/sms
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Jonas Almström Duregård
 The question then comes down to whether that warning should ever be
 strengthened to an error.

Indeed.

 I agree that such a scenario is possible. The present situation gives
 no choice but to do things badly, but things often get done badly the
 first time around anyway. Perhaps I'm just grumpy, but I think we
 should aim to make bad practice erroneous where practicable. Once
 the mistake is no longer forced upon us, it becomes a mistake that
 deserves its penalty in labour. Silent pre-emption is bad practice and
 code which relies on it should be fixed: it's not good to misconstrue
 an instance declaration because you don't know which instance
 declarations are somewhere else. Nonmonotonic reasoning is always a
 bit scary.

 From a library design perspective, we should certainly try to get these
 hierarchical choices right when we add classes. I accept that it should
 be cheap to fix mistakes (especially when the mistake is lack of
 foresight. Sticking with the warning rather than the error reduces the
 price of this particular legacy fix at the cost of tolerating misleading
 code. I agree that the balance of this trade-off is with the warning,
 for the moment, but I expect it to shift over time towards the error.
 But if it's clear what the issue is, then we can at least keep it under
 review.

I agree. Making bad practice erroneous is good, but its not really the
bad practice that raises the error here. You have no serious problems
until you try to change your bad design to a good one. Like you say it
should be cheap to fix mistakes.

 Will there be a solution to this dilemma that I have missed? Should
 the client code be allowed opt-out from the superclass preemptively
 before it is given a default? Won't that cause a similar perplexity?

 I don't know what you mean by this. Perhaps you could expand on it?

What I'm trying to ask is if you can write compatible code that will
work across gradual changes of the compiler and the libraries.

Suppose we have library with class C. In a newer version of the
library we add an intrinsic superclass S. Also suppose the compiler
implements option 1. Now the users of the library want to write code
that uses both C and S, and that's compatible with both the new and
the old library. From what I can tell there are three situations that
needs to be covered:

1) Old compiler - Old library
Here we need to specify both instances, and we cant hide the default S
instance because its not supported by the compiler. This also applies
for other situations where the client must use Haskell 2010 compatible
code.

2) New compiler - Old library
Here we also need to specify both instances.

3) New compiler - New library
We can either write both instances and hide the default or we can just
write an instance for C.

Clearly code that covers situation 1 will never be compatible with situation 3.

The question I was asking was if we are allowed to hide the default
instance of S in situation 2. In that case you can write compatible
code for situation 2 and 3. The possible confusion from this is that
you hide a default implementation thats not defined. Maybe it's not as
bad as overriding silently, but there is some room for error where you
think you have blocked a superclass instance but really you have just
blocked some completely unrelated class.

Of course we can get compatibility across all three using CPP but I
really wish we won't need that.

As time passes, situation 1 will become more rare, although situation
2 and 3 can reoccur endlessly as new libraries are designed and
redesigned.

Regards,
Jonas

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Conor McBride

Hi

On 2 Sep 2011, at 16:34, Brandon Allbery wrote:


I hope I am misunderstanding this



I wrote:

I agree that such a scenario is possible. The present situation gives
no choice but to do things badly, but things often get done badly the
first time around anyway. Perhaps I'm just grumpy, but I think we
should aim to make bad practice erroneous where practicable. Once
the mistake is no longer forced upon us, it becomes a mistake that
deserves its penalty in labour. Silent pre-emption is bad practice and


with the response:
So, when the whole point is that an unfortunate design years ago  
can't be reasonably fixed without rewriting massive amounts of code,  
the only correct answer is to rewrite massive amounts of code?


I'm not sure what you're asking here. Of course we should compare the
pain of the treatment with that of the symptoms.

 Especially when the original proposal was put forward *specifically  
to avoid* rewriting massive amounts of code?


Which original proposal? How does it avoid rewriting code?

Yes,  we'd love a perfect world.  We don't have one.  That's the  
*point*.


Recall that Option 2 resolves the duplicate superclass instances in  
favour
of an explicit prior instance, but issues a warning (which should  
offer the

data to choose between explicit resolutions). That deals with a chunk of
the legacy scenario (although it doesn't handle the situation where  
some M
is made a Monad in one module and made Applicative in a later module,  
which

is possible (common, even?) because Applicative is not currently a
superclass of Monad). If we make one existing class a superclass of  
another
existing class, some disruption is inevitable: we can try to minimize  
that
disruption, but we can't eliminate it entirely. For another example,  
if some
F is made Applicative and Traversable in the same module, which  
default Functor

instance pre-empts the other?

We should question whether the disruption of even Option 2/3 makes it  
worth
adding default superclass instances at all. Maybe, depressingly, we've  
reached
the can't-fix-it stage. It would be good to get some data. It's also  
worth
considering tools to support migration, using the diagnostics  
generated by

warnings.

If it is worth adding default superclass instances, Option 2 looks  
like a
crucial disruption-minimizing expedience, while we have a legacy of  
newly
extraneous instances to deal with. As far as an unfortunate design  
years
ago is concerned, we should be careful to minimize the amount of  
rewriting

required. If that minimum is still too much, we'd better not go there.

I'm in favour of moving to Option 1 eventually, as somehow the better  
choice

for code comprehension. But I can see reasons to resist the changeover:

  * too much unmigrated code still relying on pre-emption under  
Option 2;


  * new instances of the old problem (an existing S is suddenly made a
  superclass of an existing C, with a default S instance for C)  
come

  into being,

The former is a real risk, but hopefully with a finite lifespan. It  
would be
too costly to switch from a warning to an error while too much code  
relies on

the deprecated practice. Please don't imagine I'm in favour of that.

The latter, however, requires us to be a bit dim in a way which was  
certainly
not in evidence when most of the current motivating examples arose. In  
the
legacy code (Monad-Applicative-Functor, Traversable-Foldable-Functor),  
we've

had to choose between two bad options, but the candidate
superclass-with-default-implementation has usually been evident. I'm  
sure
we're capable of being that dim. I'm also sure we're capable of  
screwing up
by writing an instance and assuming we get the default superclass  
instance

we expect, without noticing that someone else's chunk of the codebase
pre-empts it. I'd be troubled if someone knackered my applicative- 
style use
of Monad [] by adding a zipping Applicative [], or even an instance  
which

appeared to have the same functionality but also did some sneaky
unsafePerformIO badness. That's an example of the risk we take by  
allowing

pre-emption. We have to balance the risk of going back and resolving
duplicates with the risk of bugs caused by code meaning less than it  
says.


So, are default superclass instances just too disruptive?

All the best

Conor

PS We'd love a perfect world. We don't have one. That's why we change  
things.



___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Conor McBride


On 2 Sep 2011, at 18:19, Jonas Almström Duregård wrote:


I agree. Option 2 FTW :)

The recent discussion concerns whether option 2 should eventually be
shifted to option 1. Everyone seems to agree that option 2 should be
used initially.


A similar warning should perhaps indicate that a hiding clause has
nothing to hide, as Jonas suggests.

I'm in favour of Option 2 now and Option 1 later, where later has
non-disruptiveness criteria attached. A bit like being in favour of
the pound now and the euro later.

As I've mentioned in another message just now, even Option 2 entails
some disruption, when you make one old class a new superclass-with- 
default

of another (e.g. Functor for Monad): if old code makes M a Functor in a
later module than its Monad instance, that Functor M instance comes too
late to pre-empt the default and is rejected as a duplicate.

All the best

Conor



Regards,
Jonas

On 2 September 2011 18:55, Simon Peyton-Jones  
simo...@microsoft.com wrote:
Too many words!  I'm losing track.  What I'm proposing is Option 2  
under The design of the opt-out mechanism on http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances


I believe that meets everyone's goals:
 * A warning encourages you to fix the client code
 * But you can turn it off, and it's not fatal.

Does anyone advocate something else?

Simon

| -Original Message-
| From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users-
| boun...@haskell.org] On Behalf Of Jonas Almström Duregård
| Sent: 02 September 2011 16:50
| To: Conor McBride
| Cc: GHC users
| Subject: Re: Superclass defaults
|
|  The question then comes down to whether that warning should  
ever be

|  strengthened to an error.
|
| Indeed.
|
|  I agree that such a scenario is possible. The present situation  
gives
|  no choice but to do things badly, but things often get done  
badly the

|  first time around anyway. Perhaps I'm just grumpy, but I think we
|  should aim to make bad practice erroneous where practicable. Once
|  the mistake is no longer forced upon us, it becomes a mistake  
that
|  deserves its penalty in labour. Silent pre-emption is bad  
practice and
|  code which relies on it should be fixed: it's not good to  
misconstrue

|  an instance declaration because you don't know which instance
|  declarations are somewhere else. Nonmonotonic reasoning is  
always a

|  bit scary.
| 
|  From a library design perspective, we should certainly try to  
get these
|  hierarchical choices right when we add classes. I accept that  
it should

|  be cheap to fix mistakes (especially when the mistake is lack of
|  foresight. Sticking with the warning rather than the error  
reduces the
|  price of this particular legacy fix at the cost of tolerating  
misleading
|  code. I agree that the balance of this trade-off is with the  
warning,
|  for the moment, but I expect it to shift over time towards the  
error.
|  But if it's clear what the issue is, then we can at least keep  
it under

|  review.
|
| I agree. Making bad practice erroneous is good, but its not  
really the
| bad practice that raises the error here. You have no serious  
problems
| until you try to change your bad design to a good one. Like you  
say it

| should be cheap to fix mistakes.
|
|  Will there be a solution to this dilemma that I have missed?  
Should
|  the client code be allowed opt-out from the superclass  
preemptively
|  before it is given a default? Won't that cause a similar  
perplexity?

| 
|  I don't know what you mean by this. Perhaps you could expand on  
it?

|
| What I'm trying to ask is if you can write compatible code that  
will

| work across gradual changes of the compiler and the libraries.
|
| Suppose we have library with class C. In a newer version of the
| library we add an intrinsic superclass S. Also suppose the compiler
| implements option 1. Now the users of the library want to write  
code

| that uses both C and S, and that's compatible with both the new and
| the old library. From what I can tell there are three situations  
that

| needs to be covered:
|
| 1) Old compiler - Old library
| Here we need to specify both instances, and we cant hide the  
default S
| instance because its not supported by the compiler. This also  
applies
| for other situations where the client must use Haskell 2010  
compatible

| code.
|
| 2) New compiler - Old library
| Here we also need to specify both instances.
|
| 3) New compiler - New library
| We can either write both instances and hide the default or we can  
just

| write an instance for C.
|
| Clearly code that covers situation 1 will never be compatible  
with situation 3.

|
| The question I was asking was if we are allowed to hide the default
| instance of S in situation 2. In that case you can write compatible
| code for situation 2 and 3. The possible confusion from this is  
that
| you hide a default implementation thats not defined. Maybe it's  
not as
| bad as overriding

RE: Superclass defaults

2011-09-02 Thread Simon Peyton-Jones
Too many words!  I'm losing track.  What I'm proposing is Option 2 under The 
design of the opt-out mechanism on 
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances

I believe that meets everyone's goals:
  * A warning encourages you to fix the client code
  * But you can turn it off, and it's not fatal.

Does anyone advocate something else?

Simon

| -Original Message-
| From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users-
| boun...@haskell.org] On Behalf Of Jonas Almström Duregård
| Sent: 02 September 2011 16:50
| To: Conor McBride
| Cc: GHC users
| Subject: Re: Superclass defaults
| 
|  The question then comes down to whether that warning should ever be
|  strengthened to an error.
| 
| Indeed.
| 
|  I agree that such a scenario is possible. The present situation gives
|  no choice but to do things badly, but things often get done badly the
|  first time around anyway. Perhaps I'm just grumpy, but I think we
|  should aim to make bad practice erroneous where practicable. Once
|  the mistake is no longer forced upon us, it becomes a mistake that
|  deserves its penalty in labour. Silent pre-emption is bad practice and
|  code which relies on it should be fixed: it's not good to misconstrue
|  an instance declaration because you don't know which instance
|  declarations are somewhere else. Nonmonotonic reasoning is always a
|  bit scary.
| 
|  From a library design perspective, we should certainly try to get these
|  hierarchical choices right when we add classes. I accept that it should
|  be cheap to fix mistakes (especially when the mistake is lack of
|  foresight. Sticking with the warning rather than the error reduces the
|  price of this particular legacy fix at the cost of tolerating misleading
|  code. I agree that the balance of this trade-off is with the warning,
|  for the moment, but I expect it to shift over time towards the error.
|  But if it's clear what the issue is, then we can at least keep it under
|  review.
| 
| I agree. Making bad practice erroneous is good, but its not really the
| bad practice that raises the error here. You have no serious problems
| until you try to change your bad design to a good one. Like you say it
| should be cheap to fix mistakes.
| 
|  Will there be a solution to this dilemma that I have missed? Should
|  the client code be allowed opt-out from the superclass preemptively
|  before it is given a default? Won't that cause a similar perplexity?
| 
|  I don't know what you mean by this. Perhaps you could expand on it?
| 
| What I'm trying to ask is if you can write compatible code that will
| work across gradual changes of the compiler and the libraries.
| 
| Suppose we have library with class C. In a newer version of the
| library we add an intrinsic superclass S. Also suppose the compiler
| implements option 1. Now the users of the library want to write code
| that uses both C and S, and that's compatible with both the new and
| the old library. From what I can tell there are three situations that
| needs to be covered:
| 
| 1) Old compiler - Old library
| Here we need to specify both instances, and we cant hide the default S
| instance because its not supported by the compiler. This also applies
| for other situations where the client must use Haskell 2010 compatible
| code.
| 
| 2) New compiler - Old library
| Here we also need to specify both instances.
| 
| 3) New compiler - New library
| We can either write both instances and hide the default or we can just
| write an instance for C.
| 
| Clearly code that covers situation 1 will never be compatible with situation 
3.
| 
| The question I was asking was if we are allowed to hide the default
| instance of S in situation 2. In that case you can write compatible
| code for situation 2 and 3. The possible confusion from this is that
| you hide a default implementation thats not defined. Maybe it's not as
| bad as overriding silently, but there is some room for error where you
| think you have blocked a superclass instance but really you have just
| blocked some completely unrelated class.
| 
| Of course we can get compatibility across all three using CPP but I
| really wish we won't need that.
| 
| As time passes, situation 1 will become more rare, although situation
| 2 and 3 can reoccur endlessly as new libraries are designed and
| redesigned.
| 
| Regards,
| Jonas
| 
| ___
| Glasgow-haskell-users mailing list
| Glasgow-haskell-users@haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-09-02 Thread Jonas Almström Duregård
I agree. Option 2 FTW :)

The recent discussion concerns whether option 2 should eventually be
shifted to option 1. Everyone seems to agree that option 2 should be
used initially.

Regards,
Jonas

On 2 September 2011 18:55, Simon Peyton-Jones simo...@microsoft.com wrote:
 Too many words!  I'm losing track.  What I'm proposing is Option 2 under The 
 design of the opt-out mechanism on 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances

 I believe that meets everyone's goals:
  * A warning encourages you to fix the client code
  * But you can turn it off, and it's not fatal.

 Does anyone advocate something else?

 Simon

 | -Original Message-
 | From: glasgow-haskell-users-boun...@haskell.org 
 [mailto:glasgow-haskell-users-
 | boun...@haskell.org] On Behalf Of Jonas Almström Duregård
 | Sent: 02 September 2011 16:50
 | To: Conor McBride
 | Cc: GHC users
 | Subject: Re: Superclass defaults
 |
 |  The question then comes down to whether that warning should ever be
 |  strengthened to an error.
 |
 | Indeed.
 |
 |  I agree that such a scenario is possible. The present situation gives
 |  no choice but to do things badly, but things often get done badly the
 |  first time around anyway. Perhaps I'm just grumpy, but I think we
 |  should aim to make bad practice erroneous where practicable. Once
 |  the mistake is no longer forced upon us, it becomes a mistake that
 |  deserves its penalty in labour. Silent pre-emption is bad practice and
 |  code which relies on it should be fixed: it's not good to misconstrue
 |  an instance declaration because you don't know which instance
 |  declarations are somewhere else. Nonmonotonic reasoning is always a
 |  bit scary.
 | 
 |  From a library design perspective, we should certainly try to get these
 |  hierarchical choices right when we add classes. I accept that it should
 |  be cheap to fix mistakes (especially when the mistake is lack of
 |  foresight. Sticking with the warning rather than the error reduces the
 |  price of this particular legacy fix at the cost of tolerating misleading
 |  code. I agree that the balance of this trade-off is with the warning,
 |  for the moment, but I expect it to shift over time towards the error.
 |  But if it's clear what the issue is, then we can at least keep it under
 |  review.
 |
 | I agree. Making bad practice erroneous is good, but its not really the
 | bad practice that raises the error here. You have no serious problems
 | until you try to change your bad design to a good one. Like you say it
 | should be cheap to fix mistakes.
 |
 |  Will there be a solution to this dilemma that I have missed? Should
 |  the client code be allowed opt-out from the superclass preemptively
 |  before it is given a default? Won't that cause a similar perplexity?
 | 
 |  I don't know what you mean by this. Perhaps you could expand on it?
 |
 | What I'm trying to ask is if you can write compatible code that will
 | work across gradual changes of the compiler and the libraries.
 |
 | Suppose we have library with class C. In a newer version of the
 | library we add an intrinsic superclass S. Also suppose the compiler
 | implements option 1. Now the users of the library want to write code
 | that uses both C and S, and that's compatible with both the new and
 | the old library. From what I can tell there are three situations that
 | needs to be covered:
 |
 | 1) Old compiler - Old library
 | Here we need to specify both instances, and we cant hide the default S
 | instance because its not supported by the compiler. This also applies
 | for other situations where the client must use Haskell 2010 compatible
 | code.
 |
 | 2) New compiler - Old library
 | Here we also need to specify both instances.
 |
 | 3) New compiler - New library
 | We can either write both instances and hide the default or we can just
 | write an instance for C.
 |
 | Clearly code that covers situation 1 will never be compatible with 
 situation 3.
 |
 | The question I was asking was if we are allowed to hide the default
 | instance of S in situation 2. In that case you can write compatible
 | code for situation 2 and 3. The possible confusion from this is that
 | you hide a default implementation thats not defined. Maybe it's not as
 | bad as overriding silently, but there is some room for error where you
 | think you have blocked a superclass instance but really you have just
 | blocked some completely unrelated class.
 |
 | Of course we can get compatibility across all three using CPP but I
 | really wish we won't need that.
 |
 | As time passes, situation 1 will become more rare, although situation
 | 2 and 3 can reoccur endlessly as new libraries are designed and
 | redesigned.
 |
 | Regards,
 | Jonas
 |
 | ___
 | Glasgow-haskell-users mailing list
 | Glasgow-haskell-users@haskell.org
 | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

RE: Superclass defaults

2011-08-31 Thread Simon Peyton-Jones
|  Won't option 1 Reject this as a duplicate instance declaration, which
|  indeed it is. conflict with design goal 1: a class C can be
|  re-factored into a class C with a superclass S, without disturbing any
|  clients?   

Yes, option 1 does conflict with design goal 1; good point.  There seems to be 
a lot of support for Option 3... but what about Option 2 (ie pre-empt but give 
a warning)?

I've updated the wiki page 
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances to reflect 
this discussion.

Simon


| -Original Message-
| From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users-
| boun...@haskell.org] On Behalf Of Sebastian Fischer
| Sent: 30 August 2011 03:49
| To: Bas van Dijk
| Cc: glasgow-haskell-users@haskell.org; Simon Peyton-Jones
| Subject: Re: Superclass defaults
| 
| On Mon, Aug 29, 2011 at 6:21 AM, Bas van Dijk v.dijk@gmail.com wrote:
| 
|  Won't option 1 Reject this as a duplicate instance declaration, which
|  indeed it is. conflict with design goal 1: a class C can be
|  re-factored into a class C with a superclass S, without disturbing any
|  clients?   
| 
| If yes, I prefer option 3:
| 
|  Allow the explicit to supersede the intrinsic default silently.
| 
| The argument against this option is:
| 
|  I might notice
|  that Foo is a monad and add a Monad Foo instance in my own code,
|  expecting the Applicative Foo instance to be generated in concert; to
|  my horror, I find my code has subtle bugs because the package
|  introduced a different, non-monadic, Applicative Foo instance which
|  I'm accidentally using instead.
| 
| This seems rare enough that it's feasible to issue a warning if a
| default instance is overwritten by an explicit instance in a different
| module which would prevent the described perplexity. This wouldn't,
| for example, disturb the transformers example mentioned by Bas because
| (I think) all instances are defined in the same module.
| 
| Sebastian
| 
| ___
| Glasgow-haskell-users mailing list
| Glasgow-haskell-users@haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-31 Thread Jonas Almström Duregård
|  There seems to be a lot of support for Option 3... but what about
Option 2 (ie pre-empt but give a warning)?

I think option 2 sounds very good. Possibly with the exception of only
warning when the manual instance is in another module, since you will
never experience the perplexity described in option 3 if you have
written the instance yourself. This means that most modules will not
get any warning when a class is changed to give a default superclass
instance. Even omitting the warning only when the instantiated
datatype is in the same module as the instances might be enough to
suppress most warnings.

Also i wonder if there will be a way of suppressing the warnings and
still have compatible code (with the current compiler, preferably
without using CPP)?

/J

On 31 August 2011 09:21, Simon Peyton-Jones simo...@microsoft.com wrote:
 |  Won't option 1 Reject this as a duplicate instance declaration, which
 |  indeed it is. conflict with design goal 1: a class C can be
 |  re-factored into a class C with a superclass S, without disturbing any
 |  clients?

 Yes, option 1 does conflict with design goal 1; good point.  There seems to 
 be a lot of support for Option 3... but what about Option 2 (ie pre-empt but 
 give a warning)?

 I've updated the wiki page 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances to 
 reflect this discussion.

 Simon


 | -Original Message-
 | From: glasgow-haskell-users-boun...@haskell.org 
 [mailto:glasgow-haskell-users-
 | boun...@haskell.org] On Behalf Of Sebastian Fischer
 | Sent: 30 August 2011 03:49
 | To: Bas van Dijk
 | Cc: glasgow-haskell-users@haskell.org; Simon Peyton-Jones
 | Subject: Re: Superclass defaults
 |
 | On Mon, Aug 29, 2011 at 6:21 AM, Bas van Dijk v.dijk@gmail.com wrote:
 |
 |  Won't option 1 Reject this as a duplicate instance declaration, which
 |  indeed it is. conflict with design goal 1: a class C can be
 |  re-factored into a class C with a superclass S, without disturbing any
 |  clients?
 |
 | If yes, I prefer option 3:
 |
 |  Allow the explicit to supersede the intrinsic default silently.
 |
 | The argument against this option is:
 |
 |  I might notice
 |  that Foo is a monad and add a Monad Foo instance in my own code,
 |  expecting the Applicative Foo instance to be generated in concert; to
 |  my horror, I find my code has subtle bugs because the package
 |  introduced a different, non-monadic, Applicative Foo instance which
 |  I'm accidentally using instead.
 |
 | This seems rare enough that it's feasible to issue a warning if a
 | default instance is overwritten by an explicit instance in a different
 | module which would prevent the described perplexity. This wouldn't,
 | for example, disturb the transformers example mentioned by Bas because
 | (I think) all instances are defined in the same module.
 |
 | Sebastian
 |
 | ___
 | Glasgow-haskell-users mailing list
 | Glasgow-haskell-users@haskell.org
 | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-31 Thread Conor McBride

Hi

Sorry to be late again...I'm trying to have what's laughably described
as a holiday, but it seems more like the common cold to me.

On 31 Aug 2011, at 08:52, Jonas Almström Duregård wrote:


|  There seems to be a lot of support for Option 3... but what about
Option 2 (ie pre-empt but give a warning)?


At least in the short term, I think Option 2 is a good compromise. It's
true that when I started using default superclass instances (which SHE
supports) in the Epigram codebase, the first thing I had to do was
delete a bunch of dull default instance stacks. That was fun, but it
wasn't nothing.


I think option 2 sounds very good. Possibly with the exception of only
warning when the manual instance is in another module, since you will
never experience the perplexity described in option 3 if you have
written the instance yourself.


I become perplexed very easily. I think we should warn whenever silent
pre-emption (rather than explicit) hiding is used to suppress a default
instance, because it is bad --- it makes the meaning of an instance
declaration rather more context dependent. Perhaps a design principle
should be that to understand an instance declaration, you need only
know (in addition) the tower of class declaration s above it: it is
subtle and worrying to make the meaning of one instance declaration
depend on the presence or absence of others.

Arguably, option 1 does not conflict with design goal 1. Design goal 1
supports a methodology for refining a class into a hierarchy without
creating the need for stacks of default instances or breaking code. If
the new superclass is a brand new thing without legacy instances,
there's no problem. If we'd had this mechanism in place, Functor would
always have been made a superclass of Monad, Applicative would have
been easily inserted, and we wouldn't have the stacks of manually added
default instances to worry about.

The main problem with Option 1 is in dealing with the legacy of
classes which currently require a stack of default instances, creating
a hierarchy from parts which already exist. Option 1 would create a  
bunch

of instance conflicts and thus demand changes to code. Design goal 1
isn't very explicit (sorry!) about this distinction between introducing
new classes as superclasses and building hierarchies from legacy  
classes,

but it was the former I intended. I always expected the latter to cause
trouble.

If it is also a design goal to minimize damage with respect to the
current unfortunate situation, then Option 1 is problematic. Whatever we
might wish, we are where we are. We should be pragmatic. I think we
should set Option 1 as the direction of travel, but go with Option 2 for
the moment. We should make sure that the warnings generated by Option 2
are sufficiently informative that it is easy to track down the conflicts
and resolve them explicitly, for Option 1 compliance.

Does this sound plausible?

Conor


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-31 Thread Sebastian Fischer
On Wed, Aug 31, 2011 at 4:21 PM, Simon Peyton-Jones
simo...@microsoft.com wrote:
 There seems to be a lot of support for Option 3... but what about Option 2 
 (ie pre-empt but give a warning)?

I notice that the idea to only issue a warning if the explicit and
implicit instances are in different modules was already halfway
towards reaching option 2.

I think it is fine to issue warnings also if both instances are in the
same module. For newly written code, an explicit hiding clause removes
context dependence (as Conor points out) so the warning is justified.
For existing code where it generates too much noise the warning could
be switched of selectively until the code gets cleaned up.

Sebastian

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-30 Thread Victor Nazarov
I was thinking about the design of superclass default instances. I
think that we can get relatively far using the following extensions
together:

1) Multiple instance declarations

instance (Functor[a], Monad [a])
  where
fmap = map
(=) = flip concatMap
return = (:[])

-- Declaration above is syntactic sugar for 2 declarations:
-- instance Functor[a]
--  where
--fmap = map
-- instance Monad [a]
--  where
--(=) = flip concatMap
--return = (:[])

2) Context synonyms

-- (MonadAndFunctor a) is synonym for (Functor a, Monad a)
context (Functor a, Monad a) = MonadAndFunctor a

-- Using synonims with multiple class declarations we can define instances like
instance MonadAndFunctor [a]
  where
fmap = map
(=) = flip concatMap
return = (:[])

-- Declaration above is syntactic sugar for
-- instance (Functor[a], Monad [a])
--  where
--fmap = map
--(=) = flip concatMap
--return = (:[])

3) And finally Default superclass instances

Class contains default instances for superclasses:

class Functor m = Monad m
  where
(=) :: m a - (a - m b) - m b
return :: a - m a

-- default superclass instance:
instance Functor m
  where
fmap f m = m = (return . f)

Default superclass implementations are used only when multiple
instance declarations are used:

-- no default superclass instance is used. Error is emitted when there
is no Functor instance
instance Monad [a]
  where
 ...

-- default superclass instance is used:
instance Functor [a], Monad [a]
  where
(=) = ...
return = ...

-- functor instance is generated automatically
-- fmap = ...

Suppose that we make Functor to be Monad's superclass.
Combination of this three extensions allows us to define compatibility modules:

module Control.Monad.Compat (Monad) where

import qualified Control.Monad (Monad(..), Functor(..)) as CM

context CM.Functor m, CM.Monad m = Monad m

When we have compilation failure in client code after our Monad
definition change: No Functor instance found for Foo:

instance Monad Foo
  where ...

, we simply add following two lines to the module:

import Prelude hiding (Monad)
import Control.Monad.Compat (Monad)

and compilation succeeds.

Pros:
Client code can remain Haskell 98/2010 and doesn't require any extensions.
Three extensions seems simple when separate (I think there are many
corner cases)

Cons:
Intervention is required into client code (But I think it is required anyway).

-- 
Victor Nazarov

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-29 Thread Aleksey Khudyakov
 Option 3 avoids that problem but risks perplexity: if I make use of
 some cool package which introduces some Foo :: * - *, I might notice
 that Foo is a monad and add a Monad Foo instance in my own code,
 expecting the Applicative Foo instance to be generated in concert; to
 my horror, I find my code has subtle bugs because the package
 introduced a different, non-monadic, Applicative Foo instance which
 I'm accidentally using instead.

 talks about subtle bugs. Could you give an example of such a bug?

 I would expect that the non-monadic Applicative Foo instance is always
  somehow compatible with the monadic one. However I don't have a
 clear definition of compatible yet...

I think it's something like that. Module Foo defines list and make
ZipList-like Applicative instance. Would you add standard list monad
you have a bug.

But if you add monad instance which is not compatible with existing
applicative you have bug whether you use extension or not.

module Foo where
data [a] = a : [a] | []

instance Functor [] where
  fmap = map
instamce Applicative [] where
  pure = repeat
  (*) = zipWith ($)

module Main where
instance Monad [] where
  return x = [x]
  (=) = concatMap

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-29 Thread Jonas Almström Duregård
Hi,

First of all, I love the idea of default superclass instances!

About the opt-out feature, the problem with option 3 is only present
if the superclass instance is defined in another module (you won't see
unexpected behavior from your own instances). One solution is to use
option 3 if the offending is defined in the same module and
reject/warn only when there is a superclass instance in another
module.

This way users are not surprised when the compiler rejects a
Functor/Applicative pair because they need to explicitly tell it to
hide the intrinsic Functor, and the case that Functor and Applicative
instances are defined in separate modules must be relatively rare
(outside the Applicative library)?

We might even require the data type to be defined in the same module
(which i guess is easier to check and still very common) to silently
override a default? Documenting this feature might not be very pretty
i guess...


I think the most important thing is to enable users to write
compatible code, i.e. modules that works with the Applicative class
whether it defines a default Functor or not. I suppose if option 1 is
used, hiding should be allowed even for classes that would not have
been defined anyway (with a warning)?

If we allow the Multi-headed instance declarations described in the
suggestion then we can always write compatible code by merging
instances, since an instance for (Functor,Applicative) would always
hide the default Functor instance if there is one (right?).

Regards,
Jonas


On 28 August 2011 23:21, Bas van Dijk v.dijk@gmail.com wrote:
 On 22 August 2011 10:10, Simon Peyton-Jones simo...@microsoft.com wrote:
 |  I don't completely understant how does it work. Does client need to 
 enable
 |  language extension to get default instances?
 |
 | I think that the extension would only be required to *define them*,
 | not for them to be generated. The more conservative choice would
 | indeed be to require the extension for both, though.

 Yes. I've clarified 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances to say 
 this.

 |  Also proposal cannot fix Functor/Applicative/Monad problem without 
 breaking
 |  client code. It requires explicit opt-out but client may define 
 Applicative
 |  instance. And unless hiding is added it will result in compile error.
 |
 | I think the intention (at least as I understand it) is that a
 | superclass default is only used to generate an instance if there is
 | not already some suitable instance in scope, just like a default
 | method is only used if there is not some explicit definition for the
 | method in the instance.

 Actually that is not what Conor and I proposed.  See 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances.  Under 
 Variations we discuss the silent-opt-out choice.  But it's bad enough 
 knowing exactly what instances are in scope (given that they are not named), 
 let alone having that control what further instances are or are not 
 generated!  For superclass defaults there is no such ambiguity.

 Simon


 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


 Won't option 1 Reject this as a duplicate instance declaration, which
 indeed it is. conflict with design goal 1: a class C can be
 re-factored into a class C with a superclass S, without disturbing any
 clients?

 Take the transformers package for example. It defines lot's of
 instances of Functor and Applicative for its monad transformers.
 Doesn't transformers have to be changed if we go for option 1 (by
 either dropping the Functor and Applicative instances or listing
 hiding clauses in the Monad instances) thereby seriously conflicting
 with the design goal of not disturbing any clients.

 I expected the semantics to be like option 3: Allow the explicit to
 supersede the intrinsic default silently. It has the advantage of:

 1) Not disturbing any client code.

 2) Giving the ability to define optimized implementations if you're
 not happy with the default ones (without using the hiding mechanism).

 3) Feeling very much like the semantics of default methods thereby
 conforming to the rule of least surprise.

 The argument against option 3, which I quote:

 Option 3 avoids that problem but risks perplexity: if I make use of
 some cool package which introduces some Foo :: * - *, I might notice
 that Foo is a monad and add a Monad Foo instance in my own code,
 expecting the Applicative Foo instance to be generated in concert; to
 my horror, I find my code has subtle bugs because the package
 introduced a different, non-monadic, Applicative Foo instance which
 I'm accidentally using instead.

 talks about subtle bugs. Could you give an example of such a bug?

 I would expect that the non-monadic Applicative Foo instance is always
  somehow compatible with the monadic one. However I don't have a
 clear definition of 

Re: Superclass defaults

2011-08-29 Thread Sebastian Fischer
On Mon, Aug 29, 2011 at 6:21 AM, Bas van Dijk v.dijk@gmail.com wrote:

 Won't option 1 Reject this as a duplicate instance declaration, which
 indeed it is. conflict with design goal 1: a class C can be
 re-factored into a class C with a superclass S, without disturbing any
 clients?

If yes, I prefer option 3:

 Allow the explicit to supersede the intrinsic default silently.

The argument against this option is:

 I might notice
 that Foo is a monad and add a Monad Foo instance in my own code,
 expecting the Applicative Foo instance to be generated in concert; to
 my horror, I find my code has subtle bugs because the package
 introduced a different, non-monadic, Applicative Foo instance which
 I'm accidentally using instead.

This seems rare enough that it's feasible to issue a warning if a
default instance is overwritten by an explicit instance in a different
module which would prevent the described perplexity. This wouldn't,
for example, disturb the transformers example mentioned by Bas because
(I think) all instances are defined in the same module.

Sebastian

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-28 Thread Bas van Dijk
On 22 August 2011 10:10, Simon Peyton-Jones simo...@microsoft.com wrote:
 |  I don't completely understant how does it work. Does client need to enable
 |  language extension to get default instances?
 |
 | I think that the extension would only be required to *define them*,
 | not for them to be generated. The more conservative choice would
 | indeed be to require the extension for both, though.

 Yes. I've clarified 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances to say 
 this.

 |  Also proposal cannot fix Functor/Applicative/Monad problem without 
 breaking
 |  client code. It requires explicit opt-out but client may define 
 Applicative
 |  instance. And unless hiding is added it will result in compile error.
 |
 | I think the intention (at least as I understand it) is that a
 | superclass default is only used to generate an instance if there is
 | not already some suitable instance in scope, just like a default
 | method is only used if there is not some explicit definition for the
 | method in the instance.

 Actually that is not what Conor and I proposed.  See 
 http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances.  Under 
 Variations we discuss the silent-opt-out choice.  But it's bad enough 
 knowing exactly what instances are in scope (given that they are not named), 
 let alone having that control what further instances are or are not 
 generated!  For superclass defaults there is no such ambiguity.

 Simon


 ___
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.org
 http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Won't option 1 Reject this as a duplicate instance declaration, which
indeed it is. conflict with design goal 1: a class C can be
re-factored into a class C with a superclass S, without disturbing any
clients?

Take the transformers package for example. It defines lot's of
instances of Functor and Applicative for its monad transformers.
Doesn't transformers have to be changed if we go for option 1 (by
either dropping the Functor and Applicative instances or listing
hiding clauses in the Monad instances) thereby seriously conflicting
with the design goal of not disturbing any clients.

I expected the semantics to be like option 3: Allow the explicit to
supersede the intrinsic default silently. It has the advantage of:

1) Not disturbing any client code.

2) Giving the ability to define optimized implementations if you're
not happy with the default ones (without using the hiding mechanism).

3) Feeling very much like the semantics of default methods thereby
conforming to the rule of least surprise.

The argument against option 3, which I quote:

Option 3 avoids that problem but risks perplexity: if I make use of
some cool package which introduces some Foo :: * - *, I might notice
that Foo is a monad and add a Monad Foo instance in my own code,
expecting the Applicative Foo instance to be generated in concert; to
my horror, I find my code has subtle bugs because the package
introduced a different, non-monadic, Applicative Foo instance which
I'm accidentally using instead.

talks about subtle bugs. Could you give an example of such a bug?

I would expect that the non-monadic Applicative Foo instance is always
 somehow compatible with the monadic one. However I don't have a
clear definition of compatible yet...

Thanks,

Bas

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-22 Thread Max Bolingbroke
On 21 August 2011 21:03, Alexey Khudyakov alexey.sklad...@gmail.com wrote:
 I don't completely understant how does it work. Does client need to enable
 language extension to get default instances?

I think that the extension would only be required to *define them*,
not for them to be generated. The more conservative choice would
indeed be to require the extension for both, though.

 Also proposal cannot fix Functor/Applicative/Monad problem without breaking
 client code. It requires explicit opt-out but client may define Applicative
 instance. And unless hiding is added it will result in compile error.

I think the intention (at least as I understand it) is that a
superclass default is only used to generate an instance if there is
not already some suitable instance in scope, just like a default
method is only used if there is not some explicit definition for the
method in the instance. So the hiding mechanism would only be
required to work around tricky edge cases with orphan instances.

Max

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


RE: Superclass defaults

2011-08-22 Thread Simon Peyton-Jones
|  I don't completely understant how does it work. Does client need to enable
|  language extension to get default instances?
| 
| I think that the extension would only be required to *define them*,
| not for them to be generated. The more conservative choice would
| indeed be to require the extension for both, though.

Yes. I've clarified 
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances to say this.

|  Also proposal cannot fix Functor/Applicative/Monad problem without breaking
|  client code. It requires explicit opt-out but client may define Applicative
|  instance. And unless hiding is added it will result in compile error.
| 
| I think the intention (at least as I understand it) is that a
| superclass default is only used to generate an instance if there is
| not already some suitable instance in scope, just like a default
| method is only used if there is not some explicit definition for the
| method in the instance. 

Actually that is not what Conor and I proposed.  See 
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances.  Under 
Variations we discuss the silent-opt-out choice.  But it's bad enough 
knowing exactly what instances are in scope (given that they are not named), 
let alone having that control what further instances are or are not generated!  
For superclass defaults there is no such ambiguity.

Simon


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-21 Thread Alexey Khudyakov

On 15.08.2011 14:36, Simon Peyton-Jones wrote:

With help from Conor we have made some progress on this: we have a draft design:
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances

If you care about the issue, maybe you can help resolve the above questions. In 
particular, to give
concrete evidence for (b), working out some case studies would be a Good Thing. 
The examples given in other proposals using the extension proposed here would 
be one starting point.

I don't completely understant how does it work. Does client need to 
enable language extension to get default instances?


Also proposal cannot fix Functor/Applicative/Monad problem without 
breaking client code. It requires explicit opt-out but client may define 
Applicative instance. And unless hiding is added it will result in 
compile error.


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


RE: Superclass defaults

2011-08-15 Thread Simon Peyton-Jones

|  If someone felt able to act as moderator for the discussion, willing
|  to summarise conclusions, open questions, and so on, on the wiki
|  page, that would be enormously helpful.
| 
| I'm up for that role, if that's appropriate.

I'll take you up on that, thank you!  I've added some SLPJ note notes to 
http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances which could 
perhaps do with clarifying.

Simon

PS: to avoid spam, maybe now we have advertised this thread, we should restrict 
it to ghc-users?  The *current* library question about mappend etc can stay on 
libraries.

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-15 Thread Conor McBride

[resend to GHC users, now I've subscribed!]

Hi Simon

On 15 Aug 2011, at 11:36, Simon Peyton-Jones wrote:


| Nice. But will it be happening soon, or not? And how soon is
| soon?

Not soon enough to be useful for this mappend question.

But, concerning proposed extensions to GHC about class aliases/ 
superclass defaults etc, the truth is that the biggest reason for  
inertia here at GHC HQ is not so much the implementation effort  
(athough that is always an issue).  Rather, it's uncertainty about


(a) Is there a reasonably large group of users who really want such  
a change?

   Or is it just nice to have?

(b) What is the right design?

(c) Does it pay its way? (ie do the programming benefits justify the  
cost in terms of
   both language complexity and ongoing maintenance burden of one  
more feature

   to bear in mind when changing anything)


If you care about the issue, maybe you can help resolve the above  
questions. In particular, to give
concrete evidence for (b), working out some case studies would be a  
Good Thing. The examples given in other proposals using the  
extension proposed here would be one starting point.


I can't speak for typical users, but I can relay my own experience.
I added this feature to SHE last time there was an outbreak of
Functor/Applicative/Monad, just to focus a bit of concrete thought on
the matter. Hacking on Epigram the other day, I finally got annoyed
enough (with dumb extra instances) to use it, so I wired in default
superclass instances

 Functor for Applicative, Applicative for Monad
 Functor for Traversable, Foldable for Traversable
 Alternative for MonadPlus

and then went on the rampage! Nothing broke. I got rid of a lot of
cruft. I did make essential use of

 hiding instance Functor

for structures which were both Applicative and Traversable. I cut
tens of lines for the cost of one or two hidings.

If someone felt able to act as moderator for the discussion, willing  
to summarise conclusions, open questions, and so on, on the wiki  
page, that would be enormously helpful.


I'm up for that role, if that's appropriate.

I am in too many inner loops.   But I *am* willing to contemplate  
such an extension -- it has the same flavour as default methods  
themselves, which are a very useful part of H98.


One thing that's really noticeable and sad about the status quo is that
we can't refine the structure of a bunch of related classes without
breaking established interfaces. I guess an interesting question might
be what progress is effectively being blocked by our current inability
to engineer around this problem. What are we stuck with just now?

This is a recurring issue, at least as far as mailing list heat is
concerned, but it would be good to have more evidence of substantial
impact. The Monoid vs Semigroup issue is a case in point, perhaps.
Folks, what do you think?

Cheers

Conor

PS Are there any other default superclass instances for standard classes
that SHE could usefully bake in? Sadly, we can't purge redundant methods
from standard classes just yet, but we can at least get rid of
boilerplate instances.


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-15 Thread Gábor Lehel
On Mon, Aug 15, 2011 at 12:36 PM, Simon Peyton-Jones
simo...@microsoft.com wrote:
 (Adding GHC users, and changing title.)

 | Conor McBride wrote:
 |  http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances
 |  I don't know if it's likely to be implemented in GHC anytime soon,..
 |  So things are looking up. It should soon be technically feasible to
 |  separate the issues of whether the Monoid operator should be () and
 |  whether it should actually live in a Semigroup superclass...
 |
 | Nice. But will it be happening soon, or not? And how soon is
 | soon?

 Not soon enough to be useful for this mappend question.

 But, concerning proposed extensions to GHC about class aliases/superclass 
 defaults etc, the truth is that the biggest reason for inertia here at GHC HQ 
 is not so much the implementation effort (athough that is always an issue).  
 Rather, it's uncertainty about

  (a) Is there a reasonably large group of users who really want such a change?
     Or is it just nice to have?

  (b) What is the right design?

My only input is that we have at least 2-3 (depending on whether the
latter two are to be considered separate) hierarchies in want of
refactoring: Functor/Applicative/Monad, Num and friends, and Monoid.
Ideally any solution would solve the problem for all of them, but
even if it doesn't (and only solves, say, Monad's case), I think it
should be a requirement that it at least allows for the others to be
solved as well in an incremental fashion afterwards (whether by
'upgrading' the by-then existing feature, or adding a new, orthogonal
one). The undesirable scenario would be where you would have to
change the world all over again a second time to resolve the
remaining problems.

This is just in the abstract; my brain is too under-resourced to
figure out where the proposed feature stands in relation to this. (On
its own terms, I like it.)


  (c) Does it pay its way? (ie do the programming benefits justify the cost in 
 terms of
     both language complexity and ongoing maintenance burden of one more 
 feature
     to bear in mind when changing anything)

 With help from Conor we have made some progress on this: we have a draft 
 design:
        http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances

 If you care about the issue, maybe you can help resolve the above questions. 
 In particular, to give
 concrete evidence for (b), working out some case studies would be a Good 
 Thing. The examples given in other proposals using the extension proposed 
 here would be one starting point.

 If someone felt able to act as moderator for the discussion, willing to 
 summarise conclusions, open questions, and so on, on the wiki page, that 
 would be enormously helpful.  I am in too many inner loops.   But I *am* 
 willing to contemplate such an extension -- it has the same flavour as 
 default methods themselves, which are a very useful part of H98.

 Simon

 ___
 Libraries mailing list
 librar...@haskell.org
 http://www.haskell.org/mailman/listinfo/libraries




-- 
Work is punishment for failing to procrastinate effectively.

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-15 Thread Ryan Newton

 My only input is that we have at least 2-3 (depending on whether the
 latter two are to be considered separate) hierarchies in want of
 refactoring: Functor/Applicative/Monad, Num and friends, and Monoid.
 Ideally any solution would solve the problem for all of them, but
 even if it doesn't (and only solves, say, Monad's case), I think it
 should be a requirement that it at least allows for the others to be
 solved as well in an incremental fashion afterwards (whether by
 'upgrading' the by-then existing feature, or adding a new, orthogonal
 one). The undesirable scenario would be where you would have to
 change the world all over again a second time to resolve the
 remaining problems.


Another place where this might help would be with the
RandomGen/SplittableGen issue:

   http://hackage.haskell.org/trac/ghc/ticket/4314

If design goal 1 is met, then clients would not have to refactor their
Random instance to match the new class factoring.

-Ryan
___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-15 Thread wren ng thornton

On 8/15/11 7:44 AM, Conor McBride wrote:

On 15 Aug 2011, at 11:36, Simon Peyton-Jones wrote:

But, concerning proposed extensions to GHC about class
aliases/superclass defaults etc, the truth is that the biggest reason
for inertia here at GHC HQ is not so much the implementation effort
(athough that is always an issue). Rather, it's uncertainty about

(a) Is there a reasonably large group of users who really want such a
change? Or is it just nice to have?

(b) What is the right design?

(c) Does it pay its way? (ie do the programming benefits justify the
cost in terms of both language complexity and ongoing maintenance
burden of one more feature to bear in mind when changing anything)

[...]

One thing that's really noticeable and sad about the status quo is that
we can't refine the structure of a bunch of related classes without
breaking established interfaces. I guess an interesting question might
be what progress is effectively being blocked by our current inability
to engineer around this problem. What are we stuck with just now?


Right. IMO, this concern deserves to be added to the three that Simon 
mentioned. In particular, I think this is more to the point than (a), 
though clearly in the same spirit.


We've known that the monadic and numeric towers have been in need of 
refinement for quite some time, but the status quo actively impedes 
resolving the issues with the current design. While the numeric-prelude, 
yap, and other packages have made a go at setting up new hierarchies, 
the status quo essentially forces people to buy into a single hierarchy 
for all their work because intercompatibility is just too hard. Due to 
package dependencies, this amounts to sending Haskell down the route of 
Lisp dialects, which adds additional compatibility problems to the 
original class hierarchy issues. Thus, the age-old response that people 
can set up their own class hierarchies has been shown not to work in 
practice.


To my mind, this means that Simon's (a) or my/Conor's (a') is resolved 
with certainty. The remaining issues are the uncertainty with (b) and 
(c). Naturally the answer to (c) is going to depend on the design given 
in (b). So I suppose I ought to read the wiki page about the current 
proposal :)


--
Live well,
~wren

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Superclass defaults

2011-08-15 Thread wren ng thornton

On 8/15/11 7:44 AM, Conor McBride wrote:

This is a recurring issue, at least as far as mailing list heat is
concerned, but it would be good to have more evidence of substantial
impact. The Monoid vs Semigroup issue is a case in point, perhaps.
Folks, what do you think?


For my work it'd certainly be helpful to have Semigroup broken out as a 
superclass of Monoid. So far it hasn't been important enough to make me 
want to pull in the semigroups package, but adding it to base would help 
clean things up.


One problem I see, though, is the question of what exactly is the 
right hierarchy to use. In particular, for the work I do, refactoring 
Monoid very quickly runs into the need for a Semiring class to 
replace/refactor Num, which opens an enormous can of worms. This is part 
of the reason why I continually bring up the fact that the various 
attempts at refactoring the numeric hierarchy fail, in that they ignore 
semirings and run off headlong towards fields and vector spaces (which 
are of less concern for my work; though I'd like to see modules in lieu 
of vector spaces).


Of course, the real problem is that we are only allowed to have one 
instance for a given type, whereas semirings/rings/fields/etc are 
defined by having two instances which interlock in special ways. This 
means that a proper semiring/monoid/group hierarchy is going to be 
inherently at odds with a proper semiring/ring/field hierarchy. I've yet 
to come up with a solution to this conundrum which I actually like.


--
Live well,
~wren

___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users