Let's teach GHC idiom brackets!

Hi friends, Last night I was having a good natter with Chris Done, and the topic of idiom brackets came up. Specifically, Chris' hindent and structured-haskell-mode tools have both recently become aware of the quasiquoter in applicative-quoters http://hackage.haskell.org/package/applicative-quoters - allowing one to write ordinary Haskell code but have it formatted/edited as if it wasn't even inside a quasiquoter. However, it's a shame that Chris has to now be aware of this specific quasiquoter just to get his tools to work properly. Furthermore, it's a shame that *everyone* has to do the same whenever they want to manipulate Haskell code. That said, idiom brackets - at least to me - appears to be a very desirable syntax extension. A recent desire for this came to me while working with reactive-banana. As almost everything "interesting" is even an Event or a Behavior, there tends to be a lot of assembling programs with applicative syntax. Another obvious example is when using parser combinators. Therefore, I'd like to propose that we teach GHC about this desugaring, properly. Now, how we do that, and in fact, what I'm even proposing... that's all up for discussion! I spoke briefly with David Christiansen and a few others in the Idris IRC channel last night about their particular variation of idiom brackets, and it seems people are generally happy with that. Copying that almost verbatim is probably the first proposal I'd put forward. This is the first time I've proposed an extension to GHC, so I'll need some guidance to make this happen - both in terms of guiding the discussion through to a proposal, but ultimately implementing it. Perhaps the proposal will be ready for ZuriHac, and some GHC devs could help me work on it there. Anyway, that's enough rambling from me. I would love to hear your thoughts - do you think idiom brackets are a good idea? Do you have a particular tricky case that you think they need to support? I'm all ears. -- Ollie

As a beginner Haskeller, I think my perspective might be surprising: I actually think idiom brackets would make learning and understanding Haskell *easier* for new-comers. Applicative code is intimidating to read for beginners and I have often been afraid to use it because it all seems so magical (lots of strange operators between everything!). But when I read the papers and saw idiom brackets, I suddenly realized that the whole idea was actually pretty simple! I've been pushing for them ever since.
----- Original Message -----
From: "Oliver Charles"

You can play around with idiom brackets now using the Strathclyde Haskell Enhancement (SHE)[1]. It's pretty easy to configure and will give you a good feel for how the feature behaves in practice. I haven't used Idris, and the syntax looks a bit different[2], but I suspect they're pretty similar in capability. If not, I'd love to see how they differ in detail. Personally, I'm definitely in favor of idiom brackets or similar syntax abstractly. That said, I tried using SHE's idiom brackets in some of my own existing code and was a bit underwhelmed. They're certainly an improvement for simpler cases, especially ones using operators, but fall apart quickly for more complex expressions. Now, I might have been using them incorrectly, but I found it awkward to express code that used both normal *and* Applicative application at the same time... which proved to be about half of all my code using Applicative operators. Common cases like `f <$> g x <*> h y` are a bit tricky, and they completely hose the $ operator. Now, I didn't spend much time or effort trying to make idiom brackets work, so I'm certainly not saying that they're unworkable. A good start for the proposal would be to examine more complex cases and idioms present in real code and how idiom brackets would—or wouldn't—improve them. Idris likely has some more interesting examples to start from, but there are probably enough differences in both the language and common idioms to make specific Haskell examples necessary. Adding idiom brackets to some of your own code, or code from some open source projects, would be a good way to both find relevant examples and refine the whole proposal. -tikhon On Wed, Feb 18, 2015 at 12:20 PM, Elliot Cameron < elliot.cameron@covenanteyes.com> wrote:
As a beginner Haskeller, I think my perspective might be surprising: I actually think idiom brackets would make learning and understanding Haskell *easier* for new-comers. Applicative code is intimidating to read for beginners and I have often been afraid to use it because it all seems so magical (lots of strange operators between everything!). But when I read the papers and saw idiom brackets, I suddenly realized that the whole idea was actually pretty simple! I've been pushing for them ever since.
------------------------------ *From: *"Oliver Charles"
*To: *"Haskell Cafe" *Sent: *Wednesday, February 18, 2015 2:46:16 PM *Subject: *[Haskell-cafe] Let's teach GHC idiom brackets! Hi friends,
Last night I was having a good natter with Chris Done, and the topic of idiom brackets came up. Specifically, Chris' hindent and structured-haskell-mode tools have both recently become aware of the quasiquoter in applicative-quoters http://hackage.haskell.org/package/applicative-quoters - allowing one to write ordinary Haskell code but have it formatted/edited as if it wasn't even inside a quasiquoter. However, it's a shame that Chris has to now be aware of this specific quasiquoter just to get his tools to work properly. Furthermore, it's a shame that *everyone* has to do the same whenever they want to manipulate Haskell code.
That said, idiom brackets - at least to me - appears to be a very desirable syntax extension. A recent desire for this came to me while working with reactive-banana. As almost everything "interesting" is even an Event or a Behavior, there tends to be a lot of assembling programs with applicative syntax. Another obvious example is when using parser combinators.
Therefore, I'd like to propose that we teach GHC about this desugaring, properly.
Now, how we do that, and in fact, what I'm even proposing... that's all up for discussion! I spoke briefly with David Christiansen and a few others in the Idris IRC channel last night about their particular variation of idiom brackets, and it seems people are generally happy with that. Copying that almost verbatim is probably the first proposal I'd put forward.
This is the first time I've proposed an extension to GHC, so I'll need some guidance to make this happen - both in terms of guiding the discussion through to a proposal, but ultimately implementing it. Perhaps the proposal will be ready for ZuriHac, and some GHC devs could help me work on it there.
Anyway, that's enough rambling from me. I would love to hear your thoughts - do you think idiom brackets are a good idea? Do you have a particular tricky case that you think they need to support? I'm all ears.
-- Ollie
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On Wed, Feb 18, 2015 at 4:15 PM, Tikhon Jelvis
That said, I tried using SHE's idiom brackets in some of my own existing code and was a bit underwhelmed. They're certainly an improvement for simpler cases, especially ones using operators, but fall apart quickly for more complex expressions.
My experience with them is pretty close to Tikhon's here, so I'm pretty much neutral on whether we go ahead and do this. Idiom brackets seem to have some strident supporters, I just have never personally had a case where I worked through what the idiom bracket version was and found the result appreciably clearer. When you need to mix in joins and regular application it gets quite messy. -Edward -tikhon
On Wed, Feb 18, 2015 at 12:20 PM, Elliot Cameron < elliot.cameron@covenanteyes.com> wrote:
As a beginner Haskeller, I think my perspective might be surprising: I actually think idiom brackets would make learning and understanding Haskell *easier* for new-comers. Applicative code is intimidating to read for beginners and I have often been afraid to use it because it all seems so magical (lots of strange operators between everything!). But when I read the papers and saw idiom brackets, I suddenly realized that the whole idea was actually pretty simple! I've been pushing for them ever since.
------------------------------ *From: *"Oliver Charles"
*To: *"Haskell Cafe" *Sent: *Wednesday, February 18, 2015 2:46:16 PM *Subject: *[Haskell-cafe] Let's teach GHC idiom brackets! Hi friends,
Last night I was having a good natter with Chris Done, and the topic of idiom brackets came up. Specifically, Chris' hindent and structured-haskell-mode tools have both recently become aware of the quasiquoter in applicative-quoters http://hackage.haskell.org/package/applicative-quoters - allowing one to write ordinary Haskell code but have it formatted/edited as if it wasn't even inside a quasiquoter. However, it's a shame that Chris has to now be aware of this specific quasiquoter just to get his tools to work properly. Furthermore, it's a shame that *everyone* has to do the same whenever they want to manipulate Haskell code.
That said, idiom brackets - at least to me - appears to be a very desirable syntax extension. A recent desire for this came to me while working with reactive-banana. As almost everything "interesting" is even an Event or a Behavior, there tends to be a lot of assembling programs with applicative syntax. Another obvious example is when using parser combinators.
Therefore, I'd like to propose that we teach GHC about this desugaring, properly.
Now, how we do that, and in fact, what I'm even proposing... that's all up for discussion! I spoke briefly with David Christiansen and a few others in the Idris IRC channel last night about their particular variation of idiom brackets, and it seems people are generally happy with that. Copying that almost verbatim is probably the first proposal I'd put forward.
This is the first time I've proposed an extension to GHC, so I'll need some guidance to make this happen - both in terms of guiding the discussion through to a proposal, but ultimately implementing it. Perhaps the proposal will be ready for ZuriHac, and some GHC devs could help me work on it there.
Anyway, that's enough rambling from me. I would love to hear your thoughts - do you think idiom brackets are a good idea? Do you have a particular tricky case that you think they need to support? I'm all ears.
-- Ollie
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Edward Kmett wrote:
My experience with them is pretty close to Tikhon's here, so I'm pretty much neutral on whether we go ahead and do this. Idiom brackets seem to have some strident supporters, I just have never personally had a case where I worked through what the idiom bracket version was and found the result appreciably clearer. When you need to mix in joins and regular application it gets quite messy.
I agree. I've written quite a lot of applicative code (very) long before it was even called applicative, and I never found it particularly burdensome to be explicit. On the other hand, I'd say being able to easily mix regular application and join is essential.
Do we still need idiom brackets if we have ApplicativeDo?
Wasn't aware of this proposal, but I must say it does look rather verbose compared to the explicit version, so nothing gained in that sense, and, more importantly, it obscures the key point of applicative: that arguments *cannot* depend on each other. So from that perspective, if yet more special syntax must be introduced, idiom brackets would seem preferable. But personally, I'd rather there was no more special syntax unless it truly makes a difference, like for monads and (even more so) arrows. Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham nhn@cs.nott.ac.uk This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it. Please do not use, copy or disclose the information contained in this message or in any attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. This message has been checked for viruses but the contents of an attachment may still contain software viruses which could damage your computer system, you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.

Do we still need idiom brackets if we have ApplicativeDo?
https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo
Cheers,
Bas
On 18 February 2015 at 20:46, Oliver Charles
Hi friends,
Last night I was having a good natter with Chris Done, and the topic of idiom brackets came up. Specifically, Chris' hindent and structured-haskell-mode tools have both recently become aware of the quasiquoter in applicative-quoters - allowing one to write ordinary Haskell code but have it formatted/edited as if it wasn't even inside a quasiquoter. However, it's a shame that Chris has to now be aware of this specific quasiquoter just to get his tools to work properly. Furthermore, it's a shame that everyone has to do the same whenever they want to manipulate Haskell code.
That said, idiom brackets - at least to me - appears to be a very desirable syntax extension. A recent desire for this came to me while working with reactive-banana. As almost everything "interesting" is even an Event or a Behavior, there tends to be a lot of assembling programs with applicative syntax. Another obvious example is when using parser combinators.
Therefore, I'd like to propose that we teach GHC about this desugaring, properly.
Now, how we do that, and in fact, what I'm even proposing... that's all up for discussion! I spoke briefly with David Christiansen and a few others in the Idris IRC channel last night about their particular variation of idiom brackets, and it seems people are generally happy with that. Copying that almost verbatim is probably the first proposal I'd put forward.
This is the first time I've proposed an extension to GHC, so I'll need some guidance to make this happen - both in terms of guiding the discussion through to a proposal, but ultimately implementing it. Perhaps the proposal will be ready for ZuriHac, and some GHC devs could help me work on it there.
Anyway, that's enough rambling from me. I would love to hear your thoughts - do you think idiom brackets are a good idea? Do you have a particular tricky case that you think they need to support? I'm all ears.
-- Ollie
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Bas van Dijk
Do we still need idiom brackets if we have ApplicativeDo?
I think they solve different things. ApplicativeDo is a nice extension when I need to run n different effectful computations, but either use m < n results (that is, emulating the <* and *> operators), and/or if I need to return the results in a different order. For example: do a <- x b <- y c <- z (b, a) That's going to be a pain to write using idiom brackets: (| (\a b _ -> (b, a)) x y z |) However, for the common case where you do want to apply a function to the result of all effectful computations, then ApplicativeDo just forces you to introduce new symbol names: do x' <- x y' <- y z' <- z f x' y' z' I'm against this not just due to the extra amount of typing, but choosing names is often an unnecessary cognitive burden - I've often already used up the "obvious" name, and now I'm forced to come up with another set of names, unless I want to live with shadowing warnings (not an option, I use -Werror). - Ollie

Adding context from what brought me to start thinking about using idioms: * I'm tired of writing (and reading) the awkward f <$> z <*> y <*> z pattern. * It's a pain with editor support and pretty printing (which is a solvable problem, but not the kind of problem I'd like to solve). * It feels like using >> and >>= for monads instead of do-notation. * The [i|…|] idiom quasi-quoter seems like it can solve these issues for me. So I've started trying it out on future codebases. Naturally I added support in SHM and hindent which reduces this pattern down to basic function application, which is great for editing and reading. The more function arguments, the more of a saving this is. Here's a fair comparison of before/after on my ace package's parser: https://github.com/chrisdone/ace/commit/36767780ca356db75468f803b0c91388186c... I say it's fair because this example involves mostly a low number of arguments, but a couple larger ones with obvious savings. (But I'm the kinda guy who writes do x; y instead of x >> y.) The more pathological examples come from e.g. writing JSON/Binary instances or formlets or optparse-applicative things, which regularly have >5 arguments. Pros for the template-haskell-based quasi-quoter: * It doesn't seem to add any noticeable compiling overhead to this large module (see commit message for timings). Cons: * Nesting is not supported by quasi-quoters. * 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|] Given that nobody is maintaining the applicative-quoter, I might go and add support for this extension too. That would also substantially improve the Parser.hs example above. It's quite similar to the parallel list comprehension notation. One nice thing is how trivial it is to move to and from pure to monadic/applicative code with this. 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. Ciao!

Christopher Done
Here's a fair comparison of before/after on my ace package's parser: https://github.com/chrisdone/ace/commit/36767780ca356db75468f803b0c91388186c...
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

On Thu, Feb 19, 2015 at 10:56 AM, Oliver Charles
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)
OT: you might be able to make this clearer with `where_` [1] which we defined in our opaleye utility package [2]. It feels much more natural to me than restrict, and works much better with composition outside of arrow notation. Erik [1] https://github.com/silkapp/silk-opaleye/blob/c3a324e277d730eafa9c455e1a33e67... [2] https://github.com/silkapp/silk-opaleye

Hi Ollie, Chris,
nice idea. This is something I've always thought would be nice to have
since the original paper on applicatives. However, Tikhon, Ed and
Henrik raise an important point: how would I write the following using
idiom brackets?
(,) <$> g x y <*> h (g x y)
or
f <*> g x y <*> h ((,) <$> g x y)
Does g x y need to be written (| g x y |) for the Identity Applicative?
FWIW, the original paper, http://strictlypositive.org/Idiom.pdf,
defines a neat trick to encode idiom brackets with no need for any
extensions as a solution to exercise 3 in the paper.
Best,
Mathieu
On 19 February 2015 at 10:56, Oliver Charles
Christopher Done
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/36767780ca356db75468f803b0c91388186c...
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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On 19 February 2015 at 11:37, Mathieu Boespflug
how would I write the following using idiom brackets?
(,) <$> g x y <*> h (g x y)
(| (g x y,h (g x y)) |) With applicative-quoters: [i|(,) (g x y) (h (g x y))|]
or
f <*> g x y <*> h ((,) <$> g x y)
(|id f (g x y) (h (| (g x y,)) |) |) With applicative-quoters: [i|id f (g x y) (h [i|(,) (g x y)|])|] (nesting permitting)

Although, I'm pretty sure this use of tuples is inconsistent with what's in the Applicatives paper. It'd be: [| (,) (g x y) (h (g x y))) |] [| id f (g x y) (h [| (,) (g x y)) |] |] I think that's the legit way to write it. The transformation is pretty trivial.

Christopher Done
Although, I'm pretty sure this use of tuples is inconsistent with what's in the Applicatives paper. It'd be:
[| (,) (g x y) (h (g x y))) |]
[| id f (g x y) (h [| (,) (g x y)) |] |]
I think that's the legit way to write it. The transformation is pretty trivial.
This has actually reminded me of another point. Tuples are one form of construction in Haskell that is somewhat special - but another is using record syntax. I wonder if it would be possible to use idiom brackets there to lift the record constructor too: (| T { a = x, b = y } |) This would desugar into (something like) (\a b -> T {..}) <$> x <*> y In this case, we've "lifted" the original syntax into the idiom brackets, so I think it's only natural that we're able to lift tuple construction into these brackets too. My preference would be that (| (g x y, h (g x y) |) Does the expected thing, where my expectation is (following on from my point about record syntax) would be: (\a b -> (a, b)) <$> g x y <*> h (g x y) -- Ollie

On 19 February 2015 at 13:43, Oliver Charles
This has actually reminded me of another point. Tuples are one form of construction in Haskell that is somewhat special - but another is using record syntax. I wonder if it would be possible to use idiom brackets there to lift the record constructor too:
(| T { a = x, b = y } |)
This would desugar into (something like)
(\a b -> T {..}) <$> x <*> y
Yeah, this would nicely handle: (1) being explicit about naming when you want to be, (2) order of effects.
In this case, we've "lifted" the original syntax into the idiom brackets, so I think it's only natural that we're able to lift tuple construction into these brackets too. My preference would be that
(| (g x y, h (g x y) |)
There's a wee bit of contention with (| foo |) which is supposed to be "pure foo", AIUI. I saw elsewhere someone suggest: (| g x y, h x y |) But that doesn't help with a way to involve records. -- On an unrelated note but the same topic, "applicative comprehensions" could be fun: (| f a b |) and (| f a b | a <- x, b <- y |) and (| T{..} | a <- x, b <- y |)

FWIW, the original paper, http://strictlypositive.org/Idiom.pdf, defines a neat trick to encode idiom brackets with no need for any extensions as a solution to exercise 3 in the paper.
Here's the trick explicitly for anyone who was wondering (like me)
https://gist.github.com/mpickering/99d62ccdb73f49840220
On Thu, Feb 19, 2015 at 10:37 AM, Mathieu Boespflug
Hi Ollie, Chris,
nice idea. This is something I've always thought would be nice to have since the original paper on applicatives. However, Tikhon, Ed and Henrik raise an important point: how would I write the following using idiom brackets?
(,) <$> g x y <*> h (g x y)
or
f <*> g x y <*> h ((,) <$> g x y)
Does g x y need to be written (| g x y |) for the Identity Applicative?
FWIW, the original paper, http://strictlypositive.org/Idiom.pdf, defines a neat trick to encode idiom brackets with no need for any extensions as a solution to exercise 3 in the paper.
Best,
Mathieu
On 19 February 2015 at 10:56, Oliver Charles
wrote: Christopher Done
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/36767780ca356db75468f803b0c91388186c...
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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On 19 February 2015 at 10:56, Oliver Charles
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.
Indeed, it definitely adds to the handiness to nest them.
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.
As mentioned via IRC, this is tricky due to the unclear semantic differences between x <|> y and asum [x,y] (i.e. the implicit “empty” in asum). asum1 is a solution, but partial functions like that trouble me. Generally I'd prefer to just use asum or asum1, though.
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) |)
Right, in the case that you don't want to name anything the idiom is much cleaner.
participants (10)
-
Bas van Dijk
-
Christopher Done
-
Edward Kmett
-
Elliot Cameron
-
Erik Hesselink
-
Henrik Nilsson
-
Mathieu Boespflug
-
Matthew Pickering
-
Oliver Charles
-
Tikhon Jelvis