[The reader will have noticed the absence of the words
extensible polymorphic records in the subject line]

If the long-overdue overhaul of Haskell's record system
appears to be out of scope for Haskell' (??), I suggest to add some form of first-class labels to Haskell' (to be really useful, this depends on real type classes, not the cut-down version of Haskell 98).

I often find myself coding up my own records, which is fairly
quick and painless, though of course lacking the comfort of
a real records systems (see code at bottom of this message; one might add some syntactic sugar, or not).

The two main problems I have with this are (a) the need for so-called "extensions" (I see these features merely as removing needless restrictions, and will be very disappointed if Haskell' does not provide for them, not even optionally)

(b) the need to declare my labels. it is not so much the
       typing, but:
       - possible namespace overlaps (someone might
           want to use my labels as constructor names)
       - the need for a common import origin (someone
has to declare all those labels, and all users better agree on who that someone is)

This suggestion is concerned with (b). I propose to add
first class labels to Haskell' (every label is a constant, the only inhabitant of its type). I outline three options, of which option 1 is my personal favourite, followed by option 3:

Option 1: remove the need to declare labels, make them identifiable as such in use. TREX demonstrates that this is possible.

in the past (when I was using Hugs more than GHC), I have been known to abuse TREX, not for its records, but for its labels. In other words, I'd use single-field dummy records "(mylabel=())" as labels in constructions like the one at the bottom of this message.

   pro: simple in use, labels have their own namespace,
           no conflicting imports, known to work
   con: need to give up some identifiable space in the
           language for labels

Option 2:
   add sharing imports to the module language. SML
   supports something like that, I think.

   that would allow importers to declare that the various
   imported declarations of a label are not in conflict, but
   refer to the very same type.
pro: seems like a useful feature anyway
   con: more complex than needed for this proposal,
               and would be very verbose in use

Option 3:
add a "magic" standard module Data.Label, which implicitly exports all possible labels and only such.

   that would allow all importers to refer to a common
   origin for their label declarations. imports from that
   module would amount to declarations of shared label
   types: "import Data.Label(mylabel1,mylabel2)"

   pro: no syntax extension or separate label namespace,
           no problems with common imports
   con: no separate label namespace, labels still need to
               be declared, by means of import

Either 1 or 3 should be much easier to implement than
full records, and either option would be a small change,
avoiding the main problem of a full records system: that noone can agree on what the ultimate form should look like. Either option would enable a pragmatic approach
to the problem while we are waiting for the real records.

What do you think?
Claus

related:

- tweak the existing records system (none)
   http://hackage.haskell.org/trac/haskell-prime/ticket/27

- add overlapping or incoherent instances (probably no)
   http://hackage.haskell.org/trac/haskell-prime/ticket/54

- add FunctionalDependencies (probably no)
   http://hackage.haskell.org/trac/haskell-prime/ticket/36

- add multi parameter type classes (probably yes)
   http://hackage.haskell.org/trac/haskell-prime/ticket/49

----------------------------------------
{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-overlapping-instances #-}

-- poor man's records using nested tuples and declared labels:

class Select label val rec | label rec -> val where
 sel :: rec -> label -> val

instance Select label val ((label,val),r) where
 sel ((_,val),_) label = val

instance Select label val r => Select label val (l,r) where
 sel (_,r) label = sel r label

-- some labels and examples

data A = A deriving Show
data B = B deriving Show
data C = C deriving Show
data D = D deriving Show

r1 = ((A,True),((B,'a'),((C,1),())))

r2 = ((A,False),((B,'b'),((C,2),r1)))

x1 r = (r `sel` A, r `sel` B, r `sel` C)

_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime

Reply via email to