
Maybe I'm missing something basic, but why do we need classes at all here? I propose we just desugar the list to use some functions in scope, and if they don't type-check, that's the programmer's problem. This sounds like something, which should be done with the RebindableSyntax extension. Type classes are useful, because other libraries can easily
#9883: Make OverloadedLists more usable by splitting the class interface -------------------------------------+------------------------------------- Reporter: muesli4 | Owner: Type: feature | Status: new request | Milestone: ⊥ Priority: normal | Version: 7.8.3 Component: External | Keywords: overloaded lists, Core | islist Resolution: | Architecture: Unknown/Multiple Operating System: | Difficulty: Moderate (less Unknown/Multiple | than a day) Type of failure: | Blocked By: 7495 None/Unknown | Related Tickets: #7495 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Comment (by muesli4): Replying to [comment:6 goldfire]: provide instances for it, without them you have to provide them via some third party library and it seems to me that other uses are more like a corner case. But of course I may be wrong, so I am all for usability and convenience, without excluding special cases (as I said, these could be introduced with the RebindableSyntax extension).
Concretely, here are the 7 expression forms from OverloadedLists, and my
proposal for what they desugar to:
{{{ [] -- buildList 0 (listStart `listSep` listEnd) [x] -- buildList 1 (listStart `listSep` x `listSep` listEnd) [x,y,z] -- buildList 3 (listStart `listSep` x `listSep` y `listSep`
[x .. ] -- enumFrom x [x,y ..] -- enumFromThen x y [x .. y] -- enumFromTo x y [x,y .. z] -- enumFromThenTo x y z }}}
The `enumXXX` functions would use whatever is in scope -- not necessarily the methods from `Enum`.
For regular old lists, we get
{{{ buildList _ (_:elts) = elts listStart = undefined listSep = (:) infixr 5 `listSep` listEnd = [] }}}
and the `enumXXX` functions are indeed taken from the `Enum` class.
Note that I included the fixity declaration for `listSep` above --
To me, this seems maximally flexible.
With pattern synonyms, we could mimc this behavior in patterns.
{{{ [] -- MatchList 0 (ListStart `ListSep` ListEnd) [x] -- MatchList 1 (ListStart `ListSep` x `ListSep` ListEnd) [x,y,z] -- MatchList 3 (ListStart `ListSep` x `ListSep` y `ListSep` z `ListSep` ListEnd) }}}
For regular old lists, we get
{{{ pattern MatchList n l <- ((\list -> (length list, undefined:list)) -> (n, l)) pattern ListStart <- _ pattern ListSep h t = h : t infixr 5 `ListSep` pattern ListEnd = [] }}}
The construction for `MatchList` is painful. Improvements here are welcome. Can you use different types with the same pattern? The compiler should know the length of the list, so maybe it can be expressed with a type
z `listSep` listEnd) there's no reason to disallow a ''left''-associative separator. (Though, all the elements in the list would effectively be wrapped in parentheses; the precedence level of the `listSep` fixity declaration is meaningless in the desugaring.) I like what you could achieve with it, but I don't like how you do it: * The use of {{{undefined}}} seems like a hack to make the types work. * Can you provide some use cases where different associativity is an advantage? * I don't like to use operator syntax here. * Are you able to give definitions for these functions, such that we could use the list syntax for different types in the same module? Let's say heterogenous lists (was that the intention?) and normal lists. literal (though I have no idea how to do that).
Sorry, @muesli4, I didn't mean to steal your thunder here! I hope you don't mind the debate. :) Of course, that was the reason I started the ticket. I appreciate your contribution, but I think it goes a bit over the top, my proposal was just a slight change in an already existing extension. And I don't know whether you can provide the same functionality, which currently exists.
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9883#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler