Anonymous records. A solution to the problems of record-system.

Ramana Kumar ramana at member.fsf.org
Mon Oct 14 16:29:55 UTC 2013


This list is not for "Gentlemen" only. It's best not to make that
assumption with your language.


On Mon, Oct 14, 2013 at 5:13 PM, Nikita Volkov <nikita.y.volkov at gmail.com>wrote:

> Anonymous records. A solution to the problems of record-system.
>
> The current record system is notorious for three major flaws:
>
>    1.
>
>    It does not solve the namespacing problem. I.e., you cannot have two
>    records sharing field names in a single module. E.g., the following won't
>    compile:
>
>    data A = A { field :: String }data B = B { field :: String }
>
>    2.
>
>    It's partial. The following code will result in a runtime error:
>
>    data A = A1 { field1 :: String } | A2 { field2 :: String }
>    main = print $ field1 $ A2 "abc"
>
>    3.
>
>    It does not allow you to use the same field name for different types
>    across constructors:
>
>    data A = A1 { field :: String } | A2 { field :: Int }
>
>
> This proposal approaches all the problems above and also a fourth one,
> which is unrelated to the current record system: it allows one to avoid
> declaration of intermediate types (see details below).
>
> Gentlemen, I want you to meet,
>  <#141b7bed9546ffd9_anonymous-records>Anonymous Records
>
> When a record-syntax is used in Haskell it's almost always a
> single-constructor ADT. A question rises then: why use ADT when you don't
> need its main feature (i.e., the multiple constructors)? This main feature
> is actually the root of the second and the third problem of record-syntax
> from the list above. In such situations one doesn't actually need ADT, but
> something more like a tuple with ability to access its items by name. E.g.:
>
> f :: (a :: Int, b :: String) -> Stringf rec = rec.b ++ show rec.a
>
> application:
>
> f (a = 123, b = "abc")
>
> So now you think "Okay, but how about naming it?". Well, not a problem at
> all - use the existingtype-construct:
>
> type TheRecord = (a :: Int, b :: String)
>
> Now, about the avoidance of intermediate types:
>
> type Person = (name :: String, phone :: (country :: Int, area :: Int, number :: Int))
>
> See? No need to declare separate types for inner values. But, of course,
> if you need, you still can:
>
> type Phone = (country :: Int, area :: Int, number :: Int)type Person = (name :: String, phone :: Phone)
>
> We can nicely access the deeply nested fields, e.g.:
>
> personCountryCode :: Person -> IntpersonCountryCode person = person.phone.country
>
> Okay. What about the type ambiguity? E.g., in the following the Person is
> actually the same type asCompany:
>
> type Person = (name :: String, phone :: Phone)type Company = (name :: String, phone :: Phone)
>
> Easily solvable with a help of newtype:
>
> newtype Person = Person (name :: String, phone :: Phone)newtype Company = Company (name :: String, phone :: Phone)
>
> What about ADTs? Again, easy:
>
> data Product = Tea (brand :: Company)
>              | Milk (brand :: Company, fatness :: Float)
>
> Now, the beautiful fact:
>
> This solution does not conflict with any existing feature of Haskell! As
> the examples show, it easily fits into the language as an extension. It can
> peacefully coexist with the existing record system of ADTs. Hence a
> complete backwards compatibility with old codebase. There's also a
> potential for many other additional features.
>  <#141b7bed9546ffd9_links>Links
>
>    - Source of this proposal<https://gist.github.com/nikita-volkov/6977841>
>    .
>
>
> _______________________________________________
> Haskell-prime mailing list
> Haskell-prime at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-prime
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-prime/attachments/20131014/23ea5b0d/attachment.html>


More information about the Haskell-prime mailing list