
Sun, 15 Apr 2001 14:20:01 +1000, Andrew J Bromage
We know that the most general type of `id' is "a->a". We assume there's a theoretical function:
get_the_function_type_of :: a -> String
where a can be a function type. Now consider:
f :: (String -> String) -> String f g = g (get_the_function_type_of g)
The question is: Should `f id' return "a->a" or "String->String"?
Inside f the variable g has type String->String. It doesn't matter that the expression used to build this argument could be used on another type too: the level of concreteness of the type is not a part of the object having that type, but a property of the variable through which we access it. It would return "String->String" (assuming that get_the_function_type_of was in some sense possible). Any other overloaded function would be also used as for String->String instead of reporting an ambiguity error, where using it for 'id' directly could report an ambiguity error if the instance is not defined uniformly for all types of function arguments and results but depends on a particular choice of them. In other words all instances of an overloaded function must agree on the level to which they examine the type. If one of them doesn't look at a fragment of the type (e.g. function argument), others can't too; if one of them depends on them, the type must be determined in order to make a usage unambiguous. ghc has -fallow-overlapping-instances which relaxes this requirement. It allows fallbacks: when a type doesn't fit to any instance, try to use a more general one. It still doesn't make calls which don't determine that type unambiguous, and doesn't allow to recognize the fact that a variable is polymorphic. It has some strange properties, e.g. importing a module (which defines some instances) can change a valid program into another valid program with a different meaning. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK