... | ... | @@ -33,10 +33,18 @@ Purely for the sake of argument on this page, I propose the following syntax. Fe |
|
|
|
|
|
By **constant shape** we mean that the field names of a record are given literally, though the values and types of the fields could be variables.
|
|
|
|
|
|
# Constant Record Types
|
|
|
|
|
|
|
|
|
An important difference between the various proposals is what constitutes a valid record, and similarly a valid record type. The key points are:
|
|
|
|
|
|
- Permutativity:: Are `{x :: Int, y :: Int}` and `{y :: Int, x :: Int}` the same type? The **Poor Man's Records** system distinguishes these two, which makes implementation much simpler, but means that any function which accepts permuted records must be polymorphic.
|
|
|
- Repeated Fields:: Is `{x :: Int, x :: Int}` a valid record type? Both **Poor Man's Records** and **Scoped Labels** allow this type, but other systems consider this an error.
|
|
|
|
|
|
# Type Systems
|
|
|
|
|
|
|
|
|
The most important difference between the various record proposals seems to be the expressive power of their type systems. Most systems depend on special predicates in the type context. As usual there is a trade-off between power and simplicity.
|
|
|
The most important difference between the various record proposals seems to be the expressive power of their type systems. Most systems depend on special predicates in the type context to govern the possible forms of record polymorphism. As usual there is a trade-off between power and simplicity.
|
|
|
|
|
|
<table><tr><th>No predicates</th>
|
|
|
<td>You can get away without any predicates if you are prepared to allow records to have multiple fields with the same label. In the **scoped labels** system, the syntactic form of the type matches that of the record, so you can type the operators by
|
... | ... | @@ -96,3 +104,33 @@ As it seems possible to implement most of the functionality in a library, there |
|
|
- type sharing: not specific to records, but crucial for record programming practice. If multiple modules introduce the "same" labels, means are needed to specify the equivalence of these types (cf [ Haskell prime ticket 92](http://hackage.haskell.org/trac/haskell-prime/ticket/92)).
|
|
|
- partial evaluation of type class programs: to achieve constant time record field access. Again, this feature is not specific to records, but crucial for record programming practice.
|
|
|
- portability: it would be nice if extensible records libraries were portable over multiple Haskell implementations. That not only means that these implementations need to support the same features, but that they need to interpret these features in the same way (this is currently not the case for the interaction of functional dependencies and type class overlap resolution in GHC and Hugs).
|
|
|
|
|
|
# Examples
|
|
|
|
|
|
|
|
|
Please put examples here, if possible using the above notation. The aim is to find out which features of the various systems are important in practice, so uncontrived examples which illustrate differences between the systems are wanted!
|
|
|
|
|
|
|
|
|
An example to show the need for extra polymorphism in unpermuted records:
|
|
|
|
|
|
```wiki
|
|
|
type Point = {X :: Float, Y :: Float}
|
|
|
|
|
|
norm :: Point -> Float
|
|
|
norm p = sqrt (p.X * p.X + p.Y * p.Y)
|
|
|
|
|
|
norm {Y = 3.0, X = 4.0} -- this is a type error, because X and Y are in the wrong order
|
|
|
|
|
|
norm' :: (Select X a Float, Select Y a Float) => a -> Float
|
|
|
norm' p = sqrt (p.X * p.X + p.Y * p.Y)
|
|
|
|
|
|
norm' {Y = 3.0, X = 4.0} -- this is OK, because norm' is polymorphic
|
|
|
```
|
|
|
|
|
|
|
|
|
The more complex systems support first class labels. Here is an example using the Type Families system:
|
|
|
|
|
|
```wiki
|
|
|
labelZip :: ({n :: a} `Disjoint` {m :: b}) => n -> m -> [a] -> [b] -> [{n :: a, m :: b}]
|
|
|
labelZip n m = zipWith (\x y -> {n = x, m = y})
|
|
|
``` |
|
|
\ No newline at end of file |