[GHC] #9883: Make OverloadedLists more usable by splitting the class interface
GHC
ghc-devs at haskell.org
Sat Dec 13 13:50:25 UTC 2014
#9883: Make OverloadedLists more usable by splitting the class interface
-------------------------------------+-------------------------------------
Reporter: muesli4 | Owner:
Type: feature request | Status: new
Priority: normal | Milestone: ⊥
Component: External Core | Version: 7.8.3
Keywords: overloaded lists, | Operating System:
islist | Unknown/Multiple
Architecture: Unknown/Multiple | Type of failure:
Difficulty: Moderate (less | None/Unknown
than a day) | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Revisions:
-------------------------------------+-------------------------------------
== Problem ==
While the OverloadedLists extension is very useful, it limits the types
which can be used with it, by requesting too much. Assume you have a
database specific DSEL which allows you to use list-like expressions in
queries, it's easy to implement {{{fromList}}}, but we are unable to
implement {{{toList}}} in a reasonable fashion without a backend and an
existing connection.
== Proposal ==
Modify the class interface in a way that does not require the instance to
be ''listable''.
{{{
class IsList l where
type Item l
fromList :: [Item l] -> l
fromListN :: Int -> [Item l] -> l
}}}
We could then provide the pattern matching functionality on {{{IsList}}}
instances with different approaches.
=== Another class ===
Just add another class which is used to provide the {{{toList}}} function,
used on pattern matches. This is the easiest approach
{{{
class AsList l where
type Item l
toList :: l -> [Item l]
}}}
Desugaring works as usual and it goes well with all structures. (The name
is not the best though.)
=== Using Data.Foldable ===
The list pattern gets desugared using Data.Foldable:
{{{
f :: (IsList l, Foldable l) => l -> l
f [x, y, z] = [x, y]
f l = l
}}}
gets something like:
{{{
import Data.Foldable (toList)
f :: (IsList l, Foldable l) => l -> l
f (toList -> [x, y, z]) = fromList [x, y]
f l = l
}}}
This approach does not go well with structures like {{{Data.Map}}},
because it expects the type constructor to take the ''element type'' as
first argument, but we would like to have a tuple type. Maybe a wrapper
could be provided, but I think it's not the way to go, as long as
Data.Foldable does not use type families.
== Drawbacks ==
Both approaches complicate the type of list expressions. This requires a
bit more of typing, but it specifies exactly which functionality you need
and one can simply drop the unused one, without creating dangerous dummy
implementations:
- {{{IsList}}} for overloaded list expressions
- {{{AsList}}} or {{{Foldable}}} for pattern matching
Most of the time OverloadedLists is used for convenience, so I don't
expect the normal user to be really affected, library writers,
specifically those who write some kind of DSEL, will have to be more
precise, but get a more type-safe approach, which can not fail at runtime.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9883>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list