[Hs-Generics] SYB vs HList (again)

oleg at pobox.com oleg at pobox.com
Sun Mar 25 20:52:33 EDT 2007


S. Alexander Jacobson wrote:

> I'd like be able to do something like this:
>
>    $(label Salary Int) -- template haskell to define salary label
>    main = do
>           person <- readFile "blah" >>= return . read
>           print $ person # salary
>
> In this case, haskell would assume that person has only one label, 
> salary.  The read function would ignore all the other labels.   If I 
> changed the code to this:
>
>    $(label Salary Int) -- template haskell to define salary label
>    $(label Name String)
>
>    main = do
>           person <- readFile "blah" >>= return . read
>           print $ person # salary
>           print $ show (person::Name .*. Salary)
>
> Then the code would assume that a person has both a name and a salary.

I see. You would like the pattern of using a data structure would tell
the reader which data structure it should have read. This reminds me
of how `read' is supposed to be used, although it doesn't quite work
when polymorphism is involved (cf. Num-erals). This is an interesting
problem; I should think about it. BTW, in the second example, you
supply an annotation `Name .*. Salary'. If you're willing to do that,
the problem can be solved then. I mean a function asShapeOf that is
operationally an identity. You would use it like
	let _ = person `asShapeOf` (undefined::Name .*. Salary)
or
	let _ = person `asShapeOf` (Name .*. Salary)

If you find that approach appropriate, it could be easily implemented.


> Separately, I would really like hrecords not to have order dependency. 
> It seems strange to me that (Foo .*. Bar .*. HNil) is a different type 
> from (Bar .*. Foo .*. HNil).

That is indeed strange, and inevitable to the way record polymorphism
is attained. One normally does not care about this distinction,
because many (most) of polymorphic record consumers are sufficiently
polymorphic and so accept either type. That is, if a function accepts
any subtype of the particular record type, then the issue of the order
of record fields should not arise. One may think of the type of a record
with permuted fields as being a subtype of the original record type.

There are however many cases where the record type should be
closed. Most frequently that case arises when we want to store records
in a data structure (e.g., a list). This is also the case of functions
like (==) which takes two arguments of the same type (and won't take a
subtype). In the OOHaskell library, we have a coercion function
(Actually, we have a bunch of such functions, which compute either a
meet or a join of several record types). That function will rearrange
the fields if necessary (as well as remove extra fields). In HList, it
could be implemented via h2projectByLabels.  So, one may write 
[rec1, coerce rec2, coerce rec3] and not to care of the order of fields in
rec2 or rec3. Granted, the current implementations of the coercion
functions are quite inefficient; I've been meaning to re-write them
for more than a year. Perhaps now is the time...




More information about the Generics mailing list