
Cary Cherng wrote:
What exactly is the purpose in having both records and tuples? They seem to behave rather similarly although records do have the extra naming of the fields that tuples don't.
In SML there is really no difference: In fact, in Standard ML, tuples are simply a special case of records; for example, the type int * string * bool is the same as the type { 1 : int, 2 : string, 3 : bool }. http://en.wikibooks.org/wiki/Standard_ML_Programming/Types In some programming languages (C, OCaml, Haskell), records, or structures, have to be declared and are not extensible. OCaml also has extensible records, which don't have to be declared and whose field names may be reused. Tuples may be thought of as `extensible' records that don't have to be declared (and HList takes this thought quite seriously).
data Rec1 = Rec1 { a :: Int, b :: Bool} data Rec2 = Rec2 { a :: Int, b :: Bool} foo :: Rec1 -> Bool
Rec1 and Rec2 could be in totally different code libraries. I've read that preventing Rec2 being used in foo is good for the type safety in that Rec1 and Rec2 are likely intended to have semantically different meanings and allowing interchangeability breaks this.
The reason is not type safety but type inference, or the ease of it. Given
data Rec1 = Rec1 { rec1a :: Int, rec1b :: Bool} data Rec2 = Rec2 { rec2a :: Int, rec2b :: Bool}
and the term \x -> rec2a x + 1 the type checker quickly determines that x must be of a type Rec2, and the inferred type is Rec2 -> Int. With extensible records, using OCaml: # fun x -> x#rec2a + 1;; - : < rec2a : int; .. > -> int = <fun> we infer a polymorphic type. That's all nice, until we look at the OCaml type checker and see the complexity of inference. Open records bring up lots of interesting problems (e.g., variance), which interact in interesting and not yet worked out ways with other features (e.g., GADTs). Also, open records can often mask problems. For example, in Haskell \x -> rec1a x + rec2a x won't type check but the corresponding code in OCaml will -- although the programmer may have never intended a record with both fields rec1a and rec2a. OCaml community has had a lot of experience with extensible and non-extensible records (and their dual -- extensible and non-extensible variants). The conclusion seems to be that both are needed. Often a programmer does mean closed records/variants; and non-extensible forms match the programmer's intent closely and give better, and earlier, error messages.
participants (1)
-
oleg@okmij.org