type of synthesize in Data.Generics.Schemes is too restrictive
The type of the synthesize function in Data.Generics.Schemes is unnecessarily restrictive. It's current type is
synthesize :: s -> (s -> s -> s) -> GenericQ (s -> s) -> GenericQ s
but it would be more useful if it were
synthesize :: s -> (t -> s -> s) -> GenericQ (s -> t) -> GenericQ t
Below is a contrived example demonstrating why one might want the more liberal type.
module Main where
import Data.Generics
synthesize' :: s -> (t -> s -> s) -> GenericQ (s -> t) -> GenericQ t
synthesize' z o f x = f x (foldr o z (gmapQ (synthesize' z o f) x))
-- The toTree function fails to type if synthesize' is replaced
-- with synthesize.
data ConstructorTree = ConstructorTree String [ConstructorTree]
deriving (Show)
toTree :: Data a => a -> ConstructorTree
toTree = synthesize' [] (:)
(\a s -> ConstructorTree (showConstr (toConstr a)) s)
data Foo = Bar String | Baz Foo Int deriving (Data,Typeable)
main = print (toTree (Baz (Bar "12") 5))