[Haskell-cafe] Let's teach GHC idiom brackets!

Oliver Charles ollie at ocharles.org.uk
Thu Feb 19 09:56:08 UTC 2015


Christopher Done <chrisdone at gmail.com> writes:

Hey Chris, thanks for chiming in!

> Here's a fair comparison of before/after on my ace package's parser:
> https://github.com/chrisdone/ace/commit/36767780ca356db75468f803b0c91388186c0441

In my opinion, this is exactly why I want this extension - these changes
are easier for me to parse after the changes, and would be even nicer if
we could drop the 'i' (so the brackets are symmetric). 

Interestingly, I think some of these changes could be even nicer
assuming we had ApplicativeDo as well: 

  (|SentenceCoord_2
      sentenceCoord_3
      (optional (try (do string "or"
                         sentenceCoord_2)))|)

As you can see, it allows us to do away with infix operators entirely.

> Cons:
>
> * Nesting is not supported by quasi-quoters.

This is something I think is very important - I often nest applicative
syntax in my own code, and it's essential to me that I would be able to
nest idiom brackets too.

> * Currently it lacks the Alternative support as proposed by Conor.
> That would look like this:
>
> [i|TopicalizedSentenceExistential existentialTopic (optional (try
> sentenceCoord))
>   |TopicalizedSentenceUniversal universalTopic sentenceCoord
>   |TopicalizedSentenceComposite compositeSentence|]

I'm actually somewhat against this - my personal preference is that we
keep this extension very minimal. Essentially, all we're doing is
overloading what whitespace means within the idiom brackets. Introducing
new symbols now complicates that, and introduces yet more syntax.

My current solution for dealing with sums is to use asum:

asum [[i|TopicalizedSentenceExistential existentialTopic
                                        (optional (try sentenceCoord))
     ,[i|TopicalizedSentenceUniversal universalTopic sentenceCoord |]
     ,[i|TopicalizedSentenceComposite compositeSentence|]]

Though it is a little noisy, I think it gives you want you want -
machine-predictable indentation and consistency.

> Comparatively, I've never used arrows ever and yet GHC has built-in
> support for it. Meanwhile Applicatives have wide application (hehe)
> and we're stuck writing this clunky stuff. But I figured I'd play with
> the quasi-quoter and see how it feels, and see if other people get
> onboard with it.

Interestingly there is more interaction there. It's somewhat widely
known now that Arrow <=> Applicative + Category. Thus in my current
codebase using Opaleye, I actually work entirely *without* arrow
notation. I find the notation alien-enough that it's not providing a
huge win for my productivity, but in return I end up paying a cost in a
little more typing.

  personBirthdayProduct = proc () -> do
    personRow   <- personQuery -< ()
    birthdayRow <- birthdayQuery -< ()
    returnA -< (personRow, birthdayRow)

right now becomes

     (,) <$> personQuery <*> birthdayQuery
  or liftA2 (,) personQuery birthdayQuery

but with idiom brackets becomes

  (| (personQuery, birthdayRow) |)


A slightly more complicated example is

youngPeople = proc () -> do
  row@(_, age, _) <- personQuery -< ()
  restrict -< age .<= 18
  returnA -< row

could become

  (| fst (second (lmap age restrict) . (| dup personQuery |)) |)
    where dup a = (a,a)

Arguably not considerably better as you have to tuple things up only to
immediately unpack them, but hopefully provides some insight how the use
of ArrowNotation could be replaced with idiom brackets.

- Ollie


More information about the Haskell-Cafe mailing list