Use duck typing in error classes

Let each class decide how to describe the error, rather than forcing SchemaError
to have knowledge about another class. It also means users are free to use error
descriptions in a way that suits them, rather than having to call `aggregate` just to 
get the string description.

I've left SchemaError.aggregate in place to avoid breaking uses external uses
of it, although it no longer has much purpose.