-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Member functions should be resolved at call sites #387
Comments
This works as designed. It is so that you can write
Sure, it is a restriction, but it precisely avoids the ambiguities that would arise if it was allowed. |
Nice to hear that it is working as intended, but still I think it should be changed. Consider the following scenario:
In fact, the same story applies even when both This "restriction" is a defect that destroys namespacing provided by the module system. Two functions with the same name in different modules are different functions. Users can differentiate them by qualified imports. It is natural to expect the same for methods, however, this freedom is disallowed by the (mis-)feature. As I tried to describe in my first post, they are ambiguous only when called in the As for your data Foo = Foo ... where
show (Foo ...) = "foo"
class Show a where
show :: a -> String
-- how the default implementation added by the Frege compiler
-- would look like in Haskell's syntax
default show :: HasShow a => a -> String
show x = x.show
instance Show Foo where
show (Foo ...) = "Foo ..." -- Foo.show is overridden (shadowed) Well, writing a function named |
Ok, you can give it a try.
Principles:
How to achieve: In Classes.fr, there is a function Question: how should it be handled when there is a default definition in the class but none in the instance? I propose to leave it as is, namely to take the existing type method as implementation (which will break, when the type doesn't fit). Perhaps a correction is needed for statically known instances, where the type checker replaces Here care must be taken to use the correct QName (to point whereever the actual method is located), if not done correctly already. Another point is class hierarchies. For example
will silently make a
we would have to overwrite (not overload) the If this works, we should also be able to make any type an instance of two or more different classes that happen to define the same method name! I would do it myself, but I'd first want to make your Symbol, Tau and Rho fixes work. |
There will be the problem, however, that it will not be the case that
(Contrieved, as always) The reason is how type checking for
This deferring and the second pass is necessary to avoid left-to-right bias in typechecking. In the example, the type of However, it turns out that when the proposal is implemented. the In other cases, it would force us to add a type signature to avoid type erors, namely when the type of Giving this a fourth thought: we could make it a sure thing by just typecheckig a function a second time once the type signature has been established in the first run. (Thus perhaps doubling the time for typechecking). But if we could find a way to tell whether such ambiguous constructs appeared we could re-check only where it is really needed (or maybe just stop and tell the user to supply he type signature or disambiguate) |
Thank you for your explanation. And wow... it's more complicated than I expected! I'll try it. |
@Ingo60 It turned out the current state is worse than expected. If an instance of a subclass is defined in the same module as the data, the compiler crashes. If defined in the same module as the class, the compiler silently ignores the overriding method. I don't know what happens if an instance is an orphan. I'll open a new issue for concrete examples and dedicated discussion. |
Well, it looks like this issue gives us the opportunity to clean the things up a bit. :) Matters are not that bad, as I explained in #389 Point is: we must not overload or override implementations of class members that originate from a super class of the class we're making an instance of. However, we shall find a way to overload data functions or functions that are implementations of class members of an unrelated class. I'm only afraid it will finally turn out that the cleanest solution would be to disallow the |
The compiler translates methods of an
instance
so that they can be called as if they were members of thedata
type. For example, this is legal:I believe this is done in
enter1InsDcl
.This translation (or "re-sugaring"?) comes in handy and well mixes with the syntaxes of records or Java's.
However, it becomes a problem if there are name conflicts. If
instMember
, in the above example, had been nameddataMember
, then it is a compilation error at the definition of the instance.I don't know any workaround for this issue other than renaming either of the data member or the class member.
qualified
imports doesn't work because the error occurs at instance definitions, not at use sites.The compiler should defer this transformation until such calls are encountered so that the following program would be legal:
The text was updated successfully, but these errors were encountered: