
At 2001-10-08 09:27, Diego Dainese wrote:
what are the reasons behind the rule stating that a type must not be declared as an instance of a particular class, more than once in the program?
It's so that the members of the class are unambiguous. -- class C t where foo :: t -> Integer instance C Bool where foo _ = 3; instance C Bool where foo _ = 5; ambiguous = foo True; -- GHC has a flag that will turn the rule off. -- Ashley Yakeley, Seattle WA

On Mon, 8 Oct 2001 15:03:15 -0700 Ashley Yakeley
At 2001-10-08 09:27, Diego Dainese wrote:
what are the reasons behind the rule stating that a type must not be declared as an instance of a particular class, more than once in the program?
It's so that the members of the class are unambiguous.
-- class C t where foo :: t -> Integer
instance C Bool where foo _ = 3;
instance C Bool where foo _ = 5;
ambiguous = foo True; --
OK, this is reasonable; but why are instance declarations always automatically exported and imported across modules boundary? This goes against information hiding. Consider this situation:
module M(T, f, g) where data T = ... ...
module N where import M
instance Eq T where ...
now, suppose that in a second revision of the module M, an instance of Eq is made for T; even if this instance is needed for internal use only, it outlaws the instance defined in the module N. I think this problem could be a real show-stopper for big programs... Why aren't instance declarations handled by the module system like every other symbol, so that a module can decide when to import an instance declaration and when to export it? Are there technical difficulties with this approach?
GHC has a flag that will turn the rule off.
I cannot find it! -- Diego To reply remove the 2 `x' from the address.

hello,
Why aren't instance declarations handled by the module system like every other symbol, so that a module can decide when to import an instance declaration and when to export it? Are there technical difficulties with this approach?
i beleive the reason is that instances don't have names and the module system deals with names. on the other hand i don't think this is a very good reason and completely agree with you that it is a problem. i think some work is being done on introducing named instances to Hasekll (there was a paper in the Haskell workshop i think). bye iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

"Iavor S. Diatchki" wrote:
hello,
Why aren't instance declarations handled by the module system like every other symbol, so that a module can decide when to import an instance declaration and when to export it? Are there technical difficulties with this approach?
i beleive the reason is that instances don't have names and the module system deals with names. on the other hand i don't think this is a very good reason and completely agree with you that it is a problem. i think some work is being done on introducing named instances to Hasekll (there was a paper in the Haskell workshop i think).
This is actually quite messy. The first point that needs to be made is that instance code is invoked silently. Writing x==y invokes instance code, but there is no way to say which instance should be used, so it is important that there is precisely one instance declaration in scope for that class and type. The current definition of Haskell achieves this by insisting that there is only one such declaration on the whole progam, although earlier versions achieved it by more complex, and less convenient rules, that had the advantage that they could be checked locally, at module compile time. One could envisage other means, such as defining, by some new syntactic feature, which of the possible (named) instance declarations was to be used in a particular scope. Having different instance definitions in scope at different places can casue problems, as code would just use whichever was in scope where it was invoked. This is like the dynamic scope rules of early Lisp, which is not considered good design. An alternative is to treat instances as part of the static environment at declaration time, and include them in closures when functions are passed around or exported. This ensures that a named function always uses the same instance code for the same type, but still has problems. In a language with referential transparency, one should be able to replace a function call by its body code, with substitution of arguments, (I'm assuming top-level functions with no global variables). Instances behave like global variables, so calling an imported function which brings its instances with it will in general give different results from substitution of body code for the function, and getting whichever instance is in scope at the point of call. Personally, I don't like this prospect. --brian

On Wed, 10 Oct 2001 11:20:43 +1300 Brian Boutel
"Iavor S. Diatchki" wrote:
hello,
Why aren't instance declarations handled by the module system like every other symbol, so that a module can decide when to import an instance declaration and when to export it? Are there technical difficulties with this approach?
i beleive the reason is that instances don't have names and the module system deals with names. on the other hand i don't think this is a very good reason and completely agree with you that it is a problem. i think some work is being done on introducing named instances to Hasekll (there was a paper in the Haskell workshop i think).
This is actually quite messy. The first point that needs to be made is that instance code is invoked silently. Writing x==y invokes instance code, but there is no way to say which instance should be used, so it is important that there is precisely one instance declaration in scope for that class and type. The current definition of Haskell achieves this by insisting that there is only one such declaration on the whole progam, although earlier versions achieved it by more complex, and less convenient rules, that had the advantage that they could be checked locally, at module compile time. One could envisage other means, such as defining, by some new syntactic feature, which of the possible (named) instance declarations was to be used in a particular scope.
This roughly what I have in mind: different instances declarations should be in scope in different modules.
Having different instance definitions in scope at different places can casue problems, as code would just use whichever was in scope where it was invoked. This is like the dynamic scope rules of early Lisp, which is not considered good design.
Not for sure if we consider as it is used in lisp, but the recently proposed extension outlined in the paper "implicit parameters: dynamic scoping with static types" might be more appealing...
An alternative is to treat instances as part of the static environment at declaration time, and include them in closures when functions are passed around or exported. This ensures that a named function always uses the same instance code for the same type, but still has problems. In a language with referential transparency, one should be able to replace a function call by its body code, with substitution of arguments, (I'm assuming top-level functions with no global variables). Instances behave like global variables, so calling an imported function which brings its instances with it will in general give different results from substitution of body code for the function, and getting whichever instance is in scope at the point of call. Personally, I don't like this prospect.
I'm not sure to understand correctly the 2 alternatives; my proposal is this: if a function contain a "resolved" overloaded symbol, such as (+) in
inc :: Int -> Int inc x = x+1
then the instance to use is the one in the scope of the function "inc" (ad this is included in its clousure); vice versa, if the overloaded symbol is not resolved, such as in
inc :: Num a => a -> a inc x = x+1
then the instance to use is the one in the scope of the caller of "inc"; in this case, things look pretty similar to dynamic scope, but as far as I can tell, is the same as in standard haskell. I admit I don't have thought deeply about this approach... Are there some obvious reasons to reject it? -- Diego To reply remove the 2 `x' from the address.
participants (4)
-
Ashley Yakeley
-
Brian Boutel
-
Diego Dainese
-
Iavor S. Diatchki