
#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