[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