Records in Haskell
Barney Hilken
b.hilken at ntlworld.com
Thu Sep 15 23:04:51 CEST 2011
Typos in my last message: the identifier "field" should be "Field" throughout, and "undef" should be "undefined". Here is the corrected version:
Nonextensible records with polymorphic selectors.
=================================================
1. Introduce a built-in class Label, whose members are strings at the type level. We need a notation for them; I will use double single quotes, so ''string'' is automatically an instance of Label, and you can't define other instances.
2. Define a class (in a library somewhere)
class Label n => Contains r n where
type Field r n :: *
select :: r -> n -> Field r n
update :: r -> n -> Field r n -> r
3. Declarations with field labels such as
data C = F {l1 :: t1, l2 :: t2} | G {l2 :: t2}
are syntactic sugar for
data C = F t1 t2 | G t2
instance Contains C ''l1'' where
Field C ''l1'' = t1
select (F x y) _ = x
update (F x y) _ x' = F x' y
instance Contains C ''l2'' where
Field C ''l2'' = t2
select (F x y) _ = y
select (G y) _ = y
update (F x y) _ y' = F x y'
update (G y) _ y' = G y'
4. Selector functions only need to be defined once, however many types they are used in
l1 :: Contains r ''l1'' => r -> Field r ''l1''
l1 = select r (undefined ::''l1'')
l2 :: Contains r ''l2'' => r -> Field r ''l2''
l2 = select r (undefined ::''l2'')
5. Constructors are exactly as before
6. Updates such as
r {l1 = x}
are syntactic sugar for
update r (undefined::''l1'') x
=====================================================
Sorry about that.
Barney.
More information about the Glasgow-haskell-users
mailing list