Re: Records in Haskell - updating Higher-Ranked fields

2012-03-27 Thread AntC
Gábor Lehel illissius at gmail.com writes:
 
 ..., but DORF actually requires less type system magic than
 SORF, and also already has a working prototype implementation, ...
 
 ... My main complaint against DORF is
 that having to write fieldLabel declarations for every field you want
 to use is onerous. ...
 

(Here's a possible way to reduce the need for declarations,
 for non-sharing fields; also avoid the fieldLabel new decl.)

SPJ introduced some fancy type-handling for higher-ranked fields. But still it 
only helped in accessing a H-R field, not updating it.

If we accept that updating H-R fields in liberated-namespace records is not 
possible, can we simplify the implementation? I think so. Here's what I'd call 
a well-principled work-round (not a hack, but then neither a solution).

(I'm showing it in DORF-like style, but I think it would work equally in SORF 
style with Stringy Kinds. The advantage of showing DORF is that we can try it -
- which I've done.)

You write:
data HR = HR{ objectId :: ObjectId  -- type Pun
, rev :: forall a. [a] - [a] } -- SPJ's example
 sharing (ObjectId) deriving (...)  -- new syntax
 -- this decl is not sharing `rev`, so no further code needed

 -- HR is sharing objectId, so you need a field Label in scope:
 -- probably you're already declaring newtypes/data
newtype ObjectId = ObjectId Int -- declaring a field
  deriving (Has, ... )  -- `Has` makes it a label

Field access can be polymorphic:
f :: HR - ([Bool], [Char])
f r = (r.rev [True], r.rev hello)

Record update looks like:
... myHR{ rev = Rev reverse } ...   -- annoying pun
But perhaps we could support sugar for it:
... myHR{ Rev reverse } ... -- fewer keystrokes!

The HR decl desugars to:
newtype Rev = Rev (forall a. [a] - [a])-- newtype punning
data HR = HR{ objectId :: ObjectId, rev :: Rev }
rev :: HR - (forall a. [a] - [a]) -- monotype field selector
rev r = let (Rev fn) = get r (undefined :: Rev) in fn
instance Has HR Revwhere
get HR{ rev } _ = rev   -- have to wrap the fn
set (Rev fn) HR{ .. } = HR{ rev = (Rev fn) }
type instance FieldTy HR Rev = Rev  -- have to wrap this
-- else update don't work

So I've simplified `Has` to two type arguments (like the more naieve form SPJ 
considers then rejects). And used the field's type itself as the index (so 
that we're punning on the field name):
class Has r fld   where
get :: r - fld - FieldTy r fld
set :: fld - r - SetTy r fld  -- for type change update

For the record type's `sharing` fields we desugar to:
instance Has HR ObjectId   where
get HR{ objectId } _ = objectId -- yeah dull, dull
set x HR{ .. }   = HR{ objectId = x, .. }

and the `deriving (Has)` on the newtype or data desugars to:
objectId :: {Has r ObjectId} = r - ObjectId   -- overloaded record 
objectId r = get r (undefined :: ObjectId)  -- selector
type instance FieldTy r ObjectId = ObjectId -- not parametric

AntC


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


Re: Records in Haskell -- updating higher-ranked fields: required?

2012-02-27 Thread AntC
Greg Weber greg at gregweber.info writes:

 
 
  No, I don't think anybody has a satisfactory approach to
  updating polymorphic/higher-ranked fields. (DORF mentions
  one, but it's a ghastly hack.
 
 So are the proposals dead until this is tackled, or should SORF/DORF
 propose not to allow that?
 

That's an important question. I've asked in the DORF proposal how big is the 
demand to update h-r fields?

Note that is something you can do currently with H98 records/fields.

Is it good enough to be able to extract and use h-r fields in polymorphic 
contexts? (Both SORF and DORF can do that.)

Is it good enough to be able to create records with h-r fields (using the data 
constructor)?  (Both SORF and DORF can do that.)


AntC


___
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users