
| Is this really the compiler’s job here? After all, the programmer would be able to | write | | deriving cNT' :: NT (Foo a) (Foo b) -> NT (C a) (C b) | cNT :: NT a b -> NT (C a) (C b) | cNT = cNT' . fooNT | | and expose just cNT to his users, so no expressiveness is lost by not providing | automatic support here. True. But it could get pretty inconvenient. data Foo a = F1 [a] (Tree [a]) (Maybe a) [Maybe a] We could restrict you (only ) to saying deriving fooNT :: NT [a] [b] -> NT (Tree [a]) (Tree [b]) -> NT (Maybe a) (Maybe b) -> NT [Maybe a] [Maybe b] -> NT (Foo a) (Foo b) but the excitement would wear off pretty fast :-). It'd be nicer to write deriving fooNT :: NT a b -> NT (Foo a) (Foo b) and have the compiler use the other lexically-in-scope NT values to solve the problem. This is, after all, precisely what the type-class inference machinery does. There's something a bit strange about looking for all NT values that are lexically in scope; it all amounts to something pretty similar to named type-class instances. Simon