arrowp-qq: A preprocessor and quasiquoter for translating arrow notation

[ development, library, program ] [ Propose Tags ]

A suite of preprocessor and quasiquoter to desugar arrow notation built on top of Ross Paterson's arrowp and the venerable haskell-src-exts.

[Skip to Readme]
Versions [RSS] [faq] 0.1, 0.1.1, 0.2,, 0.2.1,, 0.3.0
Dependencies arrowp-qq, base (>=4.7 && <5), containers, data-default, haskell-src-exts, haskell-src-exts-util (==0.1.0), haskell-src-meta, NoHoed, template-haskell (<2.13), transformers, uniplate [details]
License LicenseRef-GPL
Author Jose Iborra <>
Maintainer Jose Iborra <>
Revised Revision 1 made by PepeIborra at 2017-08-25T11:15:36Z
Category Development
Home page
Source repo head: git clone
Uploaded by PepeIborra at 2017-08-24T14:40:05Z
Distributions NixOS:0.3.0
Executables arrowp-ext
Downloads 4590 total (34 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2017-08-24 [all 1 reports]



Manual Flags


Enabled Hoed algorithmic debugging


Build the examples using the preprocessor and quasiquoter

Automatic Flags

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info


Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

For package maintainers and hackage trustees


Readme for arrowp-qq-0.2.1

[back to package description]

Hackage Stackage Nightly Travis Build Status


A preprocessor for arrow notation based on the arrowp preprocessor developed by Ross Paterson

Notable features include support for GHC Haskell syntax and a quasiquoter that can be used instead of the preprocessor.

Note that recent versions of GHC support this notation directly, and give better error messages to boot. But the translation produced by GHC is in some cases not as good as it could be.


The parser cannot handle banana brackets for control operators in arrow notation (the proc keyword in the original paper), due to a limitation in haskell-src-exts. In order to use banana brackets, the recommendation is to fall back to the GHC Arrows parser.

Support for GHC Haskell notation inside arrow blocks is not complete, e.g. multi-way-if and lambda case are unlikely to work as expected. If you run into one of these, please open an issue or vote for an existing one, as I plan to extend the support on demand.

Using the proc quasi quoter

addA :: Arrow a => a b Int -> a b Int -> a b Int
addA f g = [proc| x -> do
		y <- f -< x
		z <- g -< x
		returnA -< y + z |]

Using the arrowp-ext preprocessor

{-# OPTIONS -F -pgmF arrowp-ext #-}

Comparison with arrowp

arrowp-qq extends the original arrowp in three dimensions:

  1. It replaces the haskell-src based parser with one based on haskell-src-exts, which handles most of GHC 8.0.2 Haskell syntax.
  2. It provides not only a preprocessor but also a quasiquoter, which is a better option in certain cases.
  3. It extends the desugaring to handle static conditional expressions. Example:
proc inputs -> do
  results <- processor -< inputs
  if outputResultsArg
    then outputSink -< results
    else returnA -< ()
  returnA -< results

The standard arrowp (and GHC) desugaring for this code is:

  = ((processor >>> arr (\ results -> (results, results))) >>>
             (\ results -> if outputResultsArg then Left results else Right ())
             >>> (outputSink ||| returnA))
          >>> arr (\ (_, results) -> results)))

This requires an ArrowChoice, but there is a more efficient desugaring which performs the choice at compile time and thus an Arrow suffices:

((processor >>> arr (\ results -> (results, results))) >>>
          (if outputResultsArg then outputSink else arr (\ results -> ()))
          >>> arr (\ (_, results) -> results)))

Comparison with GHC

The GHC desugarer does not do a very good job of minimizing the number of first calls inserted. In certain Arrow instances, this can have a material effect on performance. Example:

trivial = proc inputs -> do
   chunked <- chunk -< inputs
   results <- process -< chunked
   returnA -< results

This code ought to desugar to a chain of arrows, and indeed, both arrowp and arrowp-qq desugar this to:

trivial = chunk >>> process

However GHC will produce (approximately) the following code:

  arr(\inputs -> (inputs,inputs)) >>> first chunk >>> first process >>> arr fst