
Hi
The draft paper feels more readable and up-to-date than the manual.
That's very true! Originally there was a manual, now there is a paper - perhaps I should take the manual down if people think that the paper is sufficiently readable?
However I have one comment about it. In the section on DERIVE for Uniplate instances, the type appearing directly in one of its own constructors is demonstrated being recognized, as is the type appearing in a list in one of its own constructors. But no mention is made of just what powers the deriving has.
The scheme outlined in the paper is very powerful - it will work for all data structures which don't contain a forall in the declaration. It can only derive instances for entirely concrete data types, i.e. you can't write an instance Maybe x, but you can write one instance Maybe Bool. (PlateData/PlateTypeable do not have this restriction).
I presume lists are a special case (how else would it be possible),
For the implementation, Data.Derive has a special case for lists, tuples and Maybe. Its a shame that only a restricted number of types are supported - things like Data.Map/Data.Set can be supported perfectly, apart from restrictions in Template Haskell. At derivation time, if Data.Derive comes across Data.Set it cannot get at Data.Set's internal structure, so it can't figure out how the instance should look. This means that the number of data types within the constructor is fixed, but can be easily extended. I'm currently deciding what to do about this. One option is to look at using SYB's reflection capabilities which do allow this, and saving the result as an instance. Another option is to add special cases for many more data types (Set/Map are both candidates). Perhaps template haskell can even be persuaded to do some of what I want - I'm still learning its power.
Also is there any restriction on the placement of lists in the constructor? I can't see how data Foo = CFoo Foo [Foo] Foo [Foo] Foo could be translated. Does putting the list somewhere other than last work?
The list can come anywhere. Consider the simplest example: data Foo = CFoo [Foo] [Foo] The instance would have the same effect as: instance Uniplate Foo where uniplate (CFoo x y) = (x ++ y, \z -> let (x2,y2) = splitAt (length x) z in CFoo x2 y2) (the actual instance would be a continuation passing variant of this, and be more efficient, but still have the same meaning) The key observation is that the length of the x field before and after is the same, so the multiple lists can be split back into their original sizes. Thanks Neil