Karl-Filip Faxen wrote
Section 5.5.2 relates to name clashes and has an interesting example towards the end:
module F where
sin :: Float -> Float sin x = (x::Float)
f x = Prelude.sin (F.sin x)
where the type signature refers to the local "sin" rather than the imported although none of them is visible unqualified. These rules are quite tricky to understand, I think. They are also different in spirit from the rules
The Haskell report seems to be inconsistent here (once again). In the beginning of section 5.3 it says Imported names serve as top level declarations: they scope over the entire body of the module but may be shadowed by local NON-TOP-LEVEL bindings. Thus, the definition of sin in module F is invalid because another top-level declaration of sin already exists due to the (implicit) import of the Prelude. In order to redefine sin locally the imported definition should be hidden and imported only qualified: module F where import Prelude hiding(sin) import qualified Prelude(sin) ...
for instance declarations in section 4.3.2 where the binding occurrences for the names of the methods must be qualified if the unqualified method name is not in scope. In the "sin" example it is allowed to resolve the name clash using the "extra" knowledge that it is illegal to provide type signatures for imported names, wheras in the case for instance declarations we may not use the corresponding "extra" knowledge that only methods in the instance'd class may be bound by the bindings.
What I'm driving at is this: I propose that top level bindings shadow imported names and that qualified names can not be used to refer to declarations in the same module.
The second part is going to conflict with the revised report which relies on the qualified names of entities in order to specify which entites exported from module M (module M) where { ... }
/kff
who feels very relieved at having come out publicly in favour of shadowing imported names ;-)
Wolfgang who prefers to forbid shadowing of imported names :-) -- Wolfgang Lux Phone: +49-251-83-38263 Institut fuer Wirtschaftinformatik FAX: +49-251-83-38259 Universitaet Muenster Email: wlux@uni-muenster.de
Hello again, Wolfgang wrote
The Haskell report seems to be inconsistent here (once again). In the beginning of section 5.3 it says
Imported names serve as top level declarations: they scope over the entire body of the module but may be shadowed by local NON-TOP-LEVEL bindings.
Thus, the definition of sin in module F is invalid because another top-level declaration of sin already exists due to the (implicit) import of the Prelude. In order to redefine sin locally the imported definition should be hidden and imported only qualified:
module F where import Prelude hiding(sin) import qualified Prelude(sin) ...
Well, it's not that simple currently. Name clashes are only illegal if they lead to unresolvable references. Thus if we have module Main where sin x = x+1 sin :: Float -> Float main = print (sin 1) then that program is illegal since in "sin 1" we cannot say which "sin" it is (from the Prelude or from Main). It is for this reason that it is legal to use qualified names to refer to top level declarations. Thus, according to the October release of the Report, the following is legal module Main where sin x = x+1 sin :: Float -> Float main = print (Prelude.sin 1, Main.sin 1) since the qualified names are different, but in my proposal, one would instead write module Main where sin x = x+1 sin :: Float -> Float main = print (Prelude.sin 1, sin 1) to get the same effect. So I do not think that the Report is really inconsistent, it is just very intricate. Shadowing imported names is a much easier rule to formulate and understand, I think. And the same programs can be written as today.
What I'm driving at is this: I propose that top level bindings shadow imported names and that qualified names can not be used to refer to declarations in the same module.
The second part is going to conflict with the revised report which relies on the qualified names of entities in order to specify which entites exported from module M (module M) where { ... }
That's right (this refers to section 5.2, fifth numbered item). What is the rationale behind requiring the qualified name to be visible also?
who prefers to forbid shadowing of imported names :-)
Even by nested bindings? /kff
hello
from module M (module M) where { ... }
That's right (this refers to section 5.2, fifth numbered item). What is the rationale behind requiring the qualified name to be visible also?
i think the idea is that when one writes "module M" in an export list, they probably mean export the entities of "M". the question is what are the entities of "M"? there are a few possible choices, here are some: 1. entities defined in module M (which are currently in scope?) 2. entities imported from module M 3. entities which may be reffered to as M.f(for some unqualified name f) 1) is probably the simplest, but doesnt seem to fit well with the haskell module system as modules may export entities, which they didnt define. this makes it difficult for a programmer to work out what will "module M" actually export. 2) is probably quite a reasonable choice, but doesnt seem to go well with the aliasing feature of the haskell module system. for example, given the import: "import X as Y" and if the programmer wanted to export a single entity "f", which came thru' this import they could write "Y.f", but if they wanted to export all such entities they would have to write "module X", and this seems awkward. 3) is (kind of) what the report currently chooses, going with the idea that if somthing may be called "M.f", it somehow belongs to "M", which i think is the rationale behind the requirement of qualified names to be inscope. there is an additional requirement however, which is probably not as intuitive. it states that the unqualified name (i.e. "f") must be inscope as well (and refer to the same thing). i think the reason for this is to avoid some clashes in exports. here is a motivating example, someone posted a few weeks ago: module A (f, module B) where import B hiding (f) import qualified B(f) f = ... this essentially provides a module, which is the same as B, execpt that it replaces the "f" function. if it wasnt for the extra condition, theer would be an export clash, as the name "f" may refer to either to the "f" defined in A, or the one imported from B. hope this helps. 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 | ==================================================
participants (3)
-
Iavor S. Diatchki -
Karl-Filip Faxen -
Wolfgang Lux