[Haskell-cafe] Records vs Tuples

oleg at okmij.org oleg at okmij.org
Tue Jan 14 08:34:01 UTC 2014


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.




More information about the Haskell-Cafe mailing list