RE: Labelled field restrictions
A perfectly sensible idea. Main difficulty I see: it's not clear what T.x would mean if both type T and module T existed, though. Also if I have data T = T { x,y::Int } data S = S { x,y::Int } I might write f :: S -> T f s = T { x = S.y s, y = S.x s } So just because I'm inside a T construction doesn't mean that "x" or "y" are unambiguous. Simon -----Original Message----- From: Garner, Robin [mailto:Robin.Garner@crsrehab.gov.au] Sent: 13 September 2002 01:57 To: 'haskell@haskell.org' Subject: Labelled field restrictions One Haskell limitation that has always puzzled me (and other programmers I have spoken with) is why labels in labelled fields share the top level name space. In practice his means that you generally name fields with some combination of constructor or type name and a field name, eg
data Rec = Con { recField1 :: Type, recField2 :: Type ... }.
Is there a good reason why field labels couldn't be optionally qualified by the type name, and usable unqualified if they are unique in the current scope ? This would be consistent with the naming rules for other top-level names, just slightly more modular. In essence, the language would implicitly do what most programmers do already, but making life easier where possible. For example, given the declarations
data Type1 = Con1 { field1 :: Type11, field2 :: Type12 }
data Type2 = Con2 { field1 :: Type21, field3 :: Type22 }
field2 and field3 could be used unqualified, but field1 would need to be referred to as Type1.field1 or Type2.field1 to disambiguate them. Additionally, within a construction using field labels (ie an x{ field = value , ...} construct), labels local to the type of x could be used unqualified as selector functions (ie in value expressions). Field names on the left-hand side of bindings would not need qualification. Essentially, the scope of the type being constructed would take priority inside the {...}. Labels from other types that clash with named labels in the local type would need to be explicitly qualified by the type name. As far as I can see, this extension wouldn't break any existing programs, but would simply complicate symbol resolution in the compiler somewhat. Robin Garner A.N.U.
hi, Simon Peyton-Jones wrote:
A perfectly sensible idea. yes, i've tought of that too and it seem like it may be useful.
Main difficulty I see: it’s not clear what T.x would mean if both type T and module T existed, though. there seem to be at least two choices - either the data qualifiers shadow the module qualifiers, or it is just ambiguous and the compiler comlains. i like the second one better, especially since with the "as" part of the imports it is very easy to rename the module qualifiers.
Also if I have
data T = T { x,y::Int }
data S = S { x,y::Int }
I might write
f :: S -> T
f s = T { x = S.y s, y = S.x s }
So just because I’m inside a T construction doesn’t mean that “x” or “y” are unambiguous. i am not sure what is the problem with this example. i can see however how something like
s { x = ... } may be ambiguous as "s" could be of type either S ot T. again in such situations the compiler could just complain. alternatively one could you use constraints as in TREX records and infer that "s is of some record type which has field x in it". by the way is there any chance of GHC supporting TREX like records? 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 | ==================================================
Hi,
there seem to be at least two choices - either the data qualifiers shadow the module qualifiers, or it is just ambiguous and the compiler comlains. i like the second one better, especially since with the "as" part of the imports it is very easy to rename the module qualifiers.
there seems to be a backwards-compatibility issue if the compiler complains on issues like this. suppose i have "legacy" code which a modeul T which exports a function x and then in module Y I import T qualified by also have data T = T {x,y::Int} then when I say T.x in Y, due to 'legacy-ness', this will refer to the function x from module T, but now if the compiler starts complaining, my code will be broken. so it seem that the second option really isn't an option (if we're in the mood of breaking code, i rather like Clean's foo.x method meaning (x foo), but...) so it seems that the only option to maintain bw compatibility would be to have the compiler default to module-level qualification, perhaps emitting a warning of ambiguity. only if it is unambiguous would it use the "new" meaning. - hal
participants (3)
-
Hal Daume III -
Iavor S. Diatchki -
Simon Peyton-Jones