[GHC] #9883: Make OverloadedLists more usable by splitting the class interface

GHC ghc-devs at haskell.org
Tue Dec 16 02:57:04 UTC 2014


#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 goldfire):

 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.

 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` z
 `listSep` listEnd)
 [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 -- 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.)

 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.

 Sorry, @muesli4, I didn't mean to steal your thunder here! I hope you
 don't mind the debate. :)

 Thoughts (anyone) on this alternative?

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9883#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list