
Dylan Thurston
On Wed, Feb 07, 2001 at 01:57:41PM -0500, Dylan Thurston wrote:
... One point that has not been made: given a class setup like <deleted> then naive users can continue to use (Num a) in contexts, and the same programs will continue to work.
I take that back. Instance declarations would change, so this isn't a very conservative change.
Would it be a terribly grave change to the language to allow leaf class instance declarations to include the necessary definitions for dependent classes? E.g. class foo a where f :: ... class (foo a) => bar a where b :: ... instance bar T where f = ... b = ... -kzm -- If I haven't seen further, it is by standing in the footprints of giants

On 08-Feb-2001, Ketil Malde
Would it be a terribly grave change to the language to allow leaf class instance declarations to include the necessary definitions for dependent classes? E.g.
class foo a where f :: ...
class (foo a) => bar a where b :: ...
instance bar T where f = ... b = ...
I think that proposal is a good idea.
It means that the user of a class which inherits from some complicated
class hierarchy doesn't need to know (or to write code which depends on)
any of the details of that class hierarchy. Instead, they can just
give instance declarations for the classes that they want to use,
and provide definitions all of the relevant members.
It means that the developer of a class can split that class into two
or more sub-classes without breaking (source level) backwards compatibility.
One point that needs to be resolved is the interaction with default methods.
Consider
class foo a where
f :: ...
f = ...
f2 :: ...
f2 = ...
class (foo a) => bar a where
b :: ...
instance bar T where
-- no definitions for f or f2
b = 42
Should this define an instance for `foo T'?
(I think not.)
How about if the instance declaration is changed to
instance bar T where
f = 41
-- no definition for f2
b = 42
?
(In that case, I think it should.)
--
Fergus Henderson

(Superficially irrelevant digression:) Simon Peyton-Jones came here today and talked about his combinator library for financial applications, as in his paper "Composing Contracts". One of the points he made was that a well-designed combinator library for financial traders should have combinators that work on a high level; then, when they want to start writing their own contracts, they can learn about a somewhat smaller set of building blocks inside that; then eventually they might learn about the fundamental building blocks. (Examples of different levels from the paper: "european"; "zcb"; "give"; "anytime".) One theory is that a well-designed class library has the same property. But standard Haskell doesn't allow this; that is why I like the proposal to allow a single instances to simultaneously declare instances of superclasses. One problem is how to present the information on the type hierarchy to users. (This is a problem in Haskell anyway; I find myself referring to the source of the Prelude while writing programs, which seems like a Bad Thing when extrapolated to larger modules.) On Thu, Feb 08, 2001 at 09:41:56PM +1100, Fergus Henderson wrote:
One point that needs to be resolved is the interaction with default methods.
Consider
class foo a where f :: ... f = ... f2 :: ... f2 = ...
class (foo a) => bar a where b :: ...
instance bar T where -- no definitions for f or f2 b = 42
Should this define an instance for `foo T'? (I think not.)
Whyever not? Because there is no textual mention of class Foo in the instance for Bar? Think about the case of a superclass with no methods; wouldn't you want to allow automatic instances in this case? One might even go further and allow a class to declare default methods for a superclass: class Foo a where f :: ... class (Foo a) => Bar a where b :: ... b = ... f = ... Best, Dylan Thurston

Thu, 8 Feb 2001 21:41:56 +1100, Fergus Henderson
Should this define an instance for `foo T'? (I think not.)
How about if the instance declaration is changed to
instance bar T where f = 41 -- no definition for f2 b = 42
? (In that case, I think it should.)
I don't like the idea of treating the case "no explicit definitions were given because all have default definitions which are OK" differently than "some explicit definitions were given". When there is a superclass, it must have an instance defined, so if we permit such thing at all, I would let it implicitly define all superclass instances not defined explicitly, or something like that. At least when all methods have default definitions. Yes, I know that they can be mutually recursive and thus all will be bottoms... So maybe there should be a way to specify that default definitions are cyclic and some of them must be defined? It is usually written in comments anyway, because it is not immediately visible in the definitions. If not formally in the language (now any method definition can be omitted even if it has no default!), then perhaps the compiler could detect most cases when methods are defined in terms of one another and give a warning. Generally the compiler could warn if the programmer has written bottom in an unusual way. For example f x = g some_expression g x = f some_expression is almost certainly a programmer error. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK

On 08-Feb-2001, Dylan Thurston
On Thu, Feb 08, 2001 at 09:41:56PM +1100, Fergus Henderson wrote:
One point that needs to be resolved is the interaction with default methods. Consider
class foo a where f :: ... f = ... f2 :: ... f2 = ...
class (foo a) => bar a where b :: ...
instance bar T where -- no definitions for f or f2 b = 42
Should this define an instance for `foo T'? (I think not.)
Whyever not?
Because too much Haskell code uses classes where the methods are defined in terms of each other: class Foo a where -- you should define either f or f2 f :: ... f = ... f2 ... f2 :: ... f2 = ... f ...
Because there is no textual mention of class Foo in the instance for Bar?
Right, and because allowing the compiler to automatically generate instances for class Foo without the programmer having considered whether those instances are OK is too dangerous.
Think about the case of a superclass with no methods; wouldn't you want to allow automatic instances in this case?
Yes.
I think Marcin has a better idea:
| So maybe there should be a way to specify that default definitions
| are cyclic and some of them must be defined?
--
Fergus Henderson

On 08-Feb-2001, Marcin 'Qrczak' Kowalczyk
I don't like the idea of treating the case "no explicit definitions were given because all have default definitions which are OK" differently than "some explicit definitions were given".
I don't really like it that much either, but...
When there is a superclass, it must have an instance defined, so if we permit such thing at all, I would let it implicitly define all superclass instances not defined explicitly, or something like that. At least when all methods have default definitions. Yes, I know that they can be mutually recursive and thus all will be bottoms...
... that is the problem I was trying to solve.
So maybe there should be a way to specify that default definitions are cyclic and some of them must be defined?
I agree 100%.
It is usually written in comments anyway, because it is not immediately visible in the definitions.
Yes. Much better to make it part of the language, so that the compiler can check it.
(now any method definition can be omitted even if it has no default!),
Yeah, that one really sucks.
--
Fergus Henderson
participants (4)
-
Dylan Thurston
-
Fergus Henderson
-
Ketil Malde
-
qrczak@knm.org.pl