Two Proposals

Yitzchak Gale gale at
Tue Oct 4 15:25:43 CEST 2011

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

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.


More information about the Glasgow-haskell-users mailing list