Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,266
    • Issues 4,266
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 394
    • Merge Requests 394
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Wiki
  • arrow notation

Last edited by Ben Gamari Apr 01, 2019
Page history New page

arrow notation

Arrow notation

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] in TcArrows.

  • #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.

Tickets

See the Arrows label.

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 tis 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.

Generalizing the types of commands

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.

Clone repository

GHC Home
GHC User's Guide

Joining In

Newcomers info
Mailing Lists & IRC
The GHC Team

Documentation

GHC Status Info
Working conventions
Building Guide
Debugging
Commentary

Wiki

Title Index
Recent Changes