I think the question here is if the datatype if abstract or not. Complex exports its (:+) constructor, so the implementation details are not hidden. Therefore it is correct to traverse its arguments. Ratio, however, does not export its (:%) constructor: Ratio is abstract, while Complex is not.
I guess then Complex should have a Data instance as it is above.
But regarding Ratio, do we want to change its gfoldl to match its current gunfoldl (as suggested before), or go the other way around, and change its gunfold, toConstr and dataTypeOf to match its gfoldl?
If we change its gfoldl, the instance is fully defined, but does not respect the data abstraction.
If we go the other way around, the instance becomes partial (gunfold and toConstr return errors), but respects the data abstraction.