[ANN] arrowp-qq: an arrowp refresh

Dear all, In case anyone finds it useful, there is a new version of arrowp in Hackage that improves the original with a much needed coat of fresh paint. Notable features include a new parser based on haskell-src-exts, a quasi quoter for arrow syntax, and improved desugaring for static choices. https://github.com/pepeiborra/arrowp https://github.com/pepeiborra/arrowp The package is in Hackage as **arrowp-qq** due to the impossibility to contact with Ross Paterson (Ross, if you are reading this, please send email!). https://hackage.haskell.org/package/arrowp-qq https://hackage.haskell.org/package/arrowp-qq For those of you reading this and wondering why would you want to use a preprocessor for something that GHC can already do, the short answer is that you probably don’t. 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 |] ``` 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 (currently only if-then-else). 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))) >>> (first (arr (\ 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))) >>> (first (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 ``` Thanks, Jose Iborra
participants (1)
-
Jose Iborra López