
George Giorgidze wrote:
My second proposal is to introduce the OverloadedLists extension that overloads list literals...
I am opposed to this proposal as stated. But I think that with a modification, it can not only be improved, but also solve the problems with the current OverloadedStrings extension. OverloadedStrings - and George's unmodified proposal - change compile time errors into run time errors. Literals with hard-to-find problems are accepted by the compiler and become _|_ at run time. An example of the problem: the xml-types package has an IsString instance for Name. The fromString method parses XML namespaces from XML names and calls error if the parse fails. Without the extension, one would specify the parts using constructors; that is wordy and awkward but checked at compile time. A quasi-quoter could be defined, but that syntax would still be far less convenient in practice than string literals. I agree that we need a way of allowing literals to have some flexibility in their types. But there should be a way for overloading to work at compile time, i.e. more like a quasi-quoter, when needed. Of course, "quasi-quoter" overloading can also just create an expression that applies a coercion function at run time. So in that sense, "quasi-quoter" overloading is more general than ad-hoc-polymorphism overloading. In all of George's examples fromList happens to be total, so there isn't an issue having it happen at run time. But if we make this generally available, you can be certain that it will cause problems later on. Just as with IsString, people will not be able to resist the nice syntax, and they will define fromList implementations that are partial. Here is a tentative modification of George's proposal: class IsList l where type Item l fromList :: [Item l] -> l listExpQ :: [ExpQ] -> ExpQ -- Minimal complete definition: fromList listExpQ = appE (varE (mkName "fromList")) . listE If the type of a list literal determines a specific instance of IsList at compile time, use the listExpQ from that instance to interpret the list literal. Otherwise, use the default listExpQ, which is just George's original proposal. An alternative would be to put listExpQ in a separate type class with an IsList constraint. IsString can similarly be extended in a backward compatible way to allow syntax checking at compile time. Here the type could be stringExpQ :: String -> ExpQ Numeric literals with Num and Integral can also be extended, though I think the problem is less common for those. Thanks, Yitz