Arrow notation (current documentation) has been in GHC for many years, but it lacks a maintainer. Even Simon PJ is very hazy about how it all works, and even toys with the idea of taking it out altogether.
Apart from the tickets below, there are a number of things that need doing
-
There no single place that describes all the moving parts of the arrow implementation, including both the typechecking and desugaring rules -- and it's very hard to work it out from the code. Simply writing out the typechecking and desugaring rules, with some commentary, would be really helpful. There is a tiny start in
Note [Arrow overview]
inTcArrows
. -
#13547: work out if existential and GADT pattern matches are allowed. If so, fix the desugarer; if not, reject them with a decent error message, not a Core Lint crash.
-
See the discussion on this Dec 16 ghc-devs thread. It started with a desire to support rebindable syntax.
-
Lower down this page are a couple of proposed changes to the notation enabled with
-XArrows
. I'm not sure of their status.
Use Keyword = Arrows
to ensure that a ticket ends up on these lists.
Open Tickets:
[\#344](http://gitlabghc.nibbler/ghc/ghc/issues/344) | arrow notation: incorrect scope of existential dictionaries |
---|---|
[\#5267](http://gitlabghc.nibbler/ghc/ghc/issues/5267) | Missing type checks for arrow command combinators |
[\#5777](http://gitlabghc.nibbler/ghc/ghc/issues/5777) | core lint error with arrow notation and GADTs |
[\#7828](http://gitlabghc.nibbler/ghc/ghc/issues/7828) | RebindableSyntax and Arrow |
[\#9985](http://gitlabghc.nibbler/ghc/ghc/issues/9985) | GHC panic with ViewPatterns and GADTs in a proc pattern |
[\#10582](http://gitlabghc.nibbler/ghc/ghc/issues/10582) | Tiny bug in lexer around lexing banana brackets |
[\#13547](http://gitlabghc.nibbler/ghc/ghc/issues/13547) | Lint error in arrows program |
[\#15175](http://gitlabghc.nibbler/ghc/ghc/issues/15175) | ghc: panic! (the 'impossible' happened) |
Closed Tickets:
[\#2722](http://gitlabghc.nibbler/ghc/ghc/issues/2722) | \<\ when compiling with -O option with ghc-6.10.0.20081019 |
---|---|
[\#3822](http://gitlabghc.nibbler/ghc/ghc/issues/3822) | guards in arrow notation (Arrows extension) case statement cause compiler panic |
[\#5022](http://gitlabghc.nibbler/ghc/ghc/issues/5022) | Core Lint error from polymorphic definitions inside arrow rec |
[\#5333](http://gitlabghc.nibbler/ghc/ghc/issues/5333) | Arrow command combinators and infixr cause the desugarer to fail |
[\#5609](http://gitlabghc.nibbler/ghc/ghc/issues/5609) | Type checking arrow notation in the presence of deferred constraints |
[\#7071](http://gitlabghc.nibbler/ghc/ghc/issues/7071) | Refactoring arrows |
[\#8505](http://gitlabghc.nibbler/ghc/ghc/issues/8505) | Arrows example error |
Changing the types of arrow operators (implemented in March 2013, for GHC 7.8)
Currently, the type of each argument of an operator (and its result) is required to have the form
a (...(e,t1), ... tn) t
where e
is a polymorphic type variable shared by all these types, but the arrow types a
can vary. The User's Guide has these examples:
ArrowPlus a => (<+>) :: a e c -> a e c -> a e c
untilA :: ArrowChoice a => a e () -> a e Bool -> a e ()
handleA :: ... => a e c -> a (e,Ex) c -> a e c
bracketA :: ... => a e b -> a (e,b) c -> a (e,c) d -> a e d
runReader :: ... => a e c -> a' (e,State) c
runState :: ... => a e c -> a' (e,State) (c,State)
bind :: Arrow a => a e b -> a (e,b) c -> a e c
bind_ :: Arrow a => a e b -> a e c -> a e c
cond :: ArrowChoice a => a e b -> a e b -> a (e,Bool) b
The problem is that to work out how many ti
s there are, the type checker needs to be able to determine whether a type is a pair type or this Skolem variable e
, and this can't be done with GHC's new constraint-based type system.
The plan is to re-arrange the shapes of the argument and result types to
a (e, (t1, ... (tn, ())...)) t
For the above examples, the new types will be
ArrowPlus a => (<+>) :: a (e,()) c -> a (e,()) c -> a (e,()) c
untilA :: ArrowChoice a => a (e,()) () -> a (e,()) Bool -> a (e,()) ()
handleA :: ... => a (e,()) c -> a (e,(Ex,())) c -> a (e,()) c
bracketA :: ... => a (e,()) b -> a (e,(b,())) c -> a (e,(c,())) d -> a (e,()) d
runReader :: ... => a (e,()) c -> a' (e,(State,())) c
runState :: ... => a (e,()) c -> a' (e,(State,())) (c,State)
bind :: Arrow a => a (e,()) b -> a (e,(b,())) c -> a (e,()) c
bind_ :: Arrow a => a (e,()) b -> a (e,()) c -> a (e,()) c
cond :: ArrowChoice a => a (e,()) b -> a (e,()) b -> a (e,(Bool,())) b
Now in the cases of (<+>)
, untilA
and bind
, the new types are specializations of the old, so those operators will still work, but the others will need to be re-defined with the new types.
The translation of many of the different varieties of command does not require the full Arrow
class, but rather just
premap :: Arrow a => (b -> b') -> a b' c -> a b c
premap f g = arr f >>> g
So the proposal is to introduce a superclass of Arrow
with just this:
class PreArrow a where
premap :: Arrow a => (b -> b') -> a b' c -> a b c
and require that class instead of Arrow
for the types of those constructs. (
libraries proposal)
This shouldn't break any code that uses arrows, but will require rewriting of instances of Arrow
.