# Why not BlockArguments?

**URL:** https://discourse.haskell.org/t/why-not-blockarguments/11885
**Category:** Learn
**Created:** [April 19, 2025, 6:42am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885 "2025-04-19T06:42:37Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![Liamzy](https://avatars.discourse-cdn.com/v4/letter/l/50afbb/32.png) [@Liamzy](https://discourse.haskell.org/u/Liamzy)
#### Post date: [April 19, 2025, 6:42am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/1 "2025-04-19T06:42:37Z")

</div>

I don’t use BlockArguments because I try to minimize the number of extensions I use, but what’s the argument of keeping BlockArguments out of GHC editions? I’m under the impression that it’s always on the verge of being added to the next GHC20xx, but something stops it. But then again, LambdaCase was in the same situation.

---

<div class="post-metadata">

### Author: ![f-a](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/f-a/32/2740_2.png) [@f-a](https://discourse.haskell.org/u/f-a)
#### Post date: [April 19, 2025, 7:52am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/2 "2025-04-19T07:52:39Z")

</div>

Apparently [no strong opposition, but not much love either](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0613-ghc2024.rst#tally).

[The relevant ticket](https://github.com/ghc-proposals/ghc-proposals/pull/613) similarly has little discussion about `BlockArguments`, no-one wrote against it, supporting voices were few.

[Community](http://discourse.haskell.org/t/ghc2024-community-input/8168) was more receptive of the idea.

---

<div class="post-metadata">

### Author: ![jmcarthur](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jmcarthur/32/3283_2.png) [@jmcarthur](https://discourse.haskell.org/u/jmcarthur)
#### Post date: [April 19, 2025, 2:16pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/3 "2025-04-19T14:16:56Z")

</div>

I personally love `BlockArguments` and use it all over the place, but it’s a very minor improvement, especially if `($)` doesn’t feel a bit dirty to you. If your discipline is to use per-module language pragmas for every extension, it feels like a pretty large amount of boilerplate for such a minor improvement. Counting characters is not my favorite way to appraise syntax sugar, but since it’s a simple metric, consider how many uses of `($)` I need to be able to eliminate in order to pay for the characters used by the language pragma.

```haskell
{-# Language BlockArguments #-}

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6

```

If this is my criteria, my module must have _sixteen_ `($)`s that I can eliminate before I would even consider it worth enabling, and then I will end up changing a lot of code.

A different approach is to always enable the extension by default and just consider it part of your standard module boilerplate, that way the barrier is paid for in advance, and you might as well just use block arguments instead of `($)` immediately when you write the code, but that feels costly, too. I, personally, add it to the `default-extensions` in my `.cabal` file, but I understand that most people like to enable extensions more locally to aide comprehension.

All of this would be addressed by enabling the extension by default, but default extensions usually have to be pretty universally loved already, which is tough due to the boilerplate. It’s a chicken and egg problem that makes `BlockArguments` a bit difficult to get in via a voting process.

---

<div class="post-metadata">

### Author: ![lorenzo](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lorenzo/32/1294_2.png) [@lorenzo](https://discourse.haskell.org/u/lorenzo)
#### Post date: [April 19, 2025, 5:18pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/4 "2025-04-19T17:18:40Z")

</div>

I love BlockArguments, it makes code significantly more readable. I hope it gets included in the next edition by default.

---

<div class="post-metadata">

### Author: ![Tikhon](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tikhon/32/3667_2.png) [@Tikhon](https://discourse.haskell.org/u/Tikhon)
#### Post date: [April 19, 2025, 6:39pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/5 "2025-04-19T18:39:24Z")

</div>

> it’s a very minor improvement, especially if `($)` doesn’t feel a bit dirty to you.

100% agree. I like it myself, but I recognize it’s a marginal improvement. If you already have the habit of putting `$` where you need it, I can totally understand why you wouldn’t get over the activation energy to switch your style to `BlockArguments`.

That said, it seems like we could have a lower threshold for including “small” extensions like this as defaults. (As far as I know) `BlockArguments` does not break any existing code and there’s no real cost to enabling it. It’s only an extension for historical reasons; if that syntax had been valid from the beginning, nobody would bat an eye at it.

People regularly cite Haskell extensions as something that makes the language harder to learn. Language editions are the mechanism we currently have to help manage this. Rolling small, backwards-compatible extensions into editions would be a sort of “extension housekeeping”: ideally we’d be able to start treating these changes as just parts of the base language rather than extensions that newcomers have to explicitly track and understand.

I don’t know how effective language editions are in this regard but, since they’re our primary option right now, I’m in favor of using them more rather than less 🙂

---

<div class="post-metadata">

### Author: ![arybczak](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/arybczak/32/2527_2.png) [@arybczak](https://discourse.haskell.org/u/arybczak)
#### Post date: [April 19, 2025, 6:54pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/6 "2025-04-19T18:54:17Z")

</div>

`BlockArguments` has a large con in that there’s currently no way for the compiler or external tool like hlint to tell you that `$` is redundant. The result is that you can either use `$` or not and this introduces inconsistency and potential pointless discussions during code review, so I never enable it.

---

<div class="post-metadata">

### Author: ![Ambrose](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ambrose/32/5672_2.png) [@Ambrose](https://discourse.haskell.org/u/Ambrose)
#### Post date: [April 19, 2025, 8:01pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/7 "2025-04-19T20:01:16Z")

</div>

I think discussing whether a `$` is redundant in code review just shouldn’t happen lol. Not worth the time it takes to type it or read it 😆

---

<div class="post-metadata">

### Author: ![prophet](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/prophet/32/5031_2.png) [@prophet](https://discourse.haskell.org/u/prophet)
#### Post date: [April 19, 2025, 9:03pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/8 "2025-04-19T21:03:27Z")

</div>

I feel like this is already constantly the case in Haskell though, isn’t it?  
E.g. you might write `f (g (h x))` or `f $ g $ h x` or even `f . g . h $ x` (or anything in between).  
All of these could be pointlessly argued about, depending on which style people prefer

---

<div class="post-metadata">

### Author: ![rhendric](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rhendric/32/2689_2.png) [@rhendric](https://discourse.haskell.org/u/rhendric)
#### Post date: [April 19, 2025, 10:53pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/9 "2025-04-19T22:53:49Z")

</div>

> [@arybczak](#):
>
> `BlockArguments` has a large con in that there’s currently no way for the compiler or external tool like hlint to tell you that `$` is redundant.

[Okay](https://github.com/ndmitchell/hlint/pull/1642), next objection?

---

<div class="post-metadata">

### Author: ![Leary](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/leary/32/4348_2.png) [@Leary](https://discourse.haskell.org/u/Leary)
#### Post date: [April 20, 2025, 12:59am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/10 "2025-04-20T00:59:55Z")

</div>

`BlockArguments` is not so much a language extension as a bugfix for the spec—it’s almost always the first “extension” I enable.

I would have argued strongly for its inclusion in `GHC2021` or `GHC2024`, but frankly I never noticed any of these discussions were taking place.

---

<div class="post-metadata">

### Author: ![Liamzy](https://avatars.discourse-cdn.com/v4/letter/l/50afbb/32.png) [@Liamzy](https://discourse.haskell.org/u/Liamzy)
#### Post date: [April 20, 2025, 9:03am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/11 "2025-04-20T09:03:38Z")

</div>

So, I guess, when GHC2027 comes up for discussion, people will be reminded to go plug “There’s no good reason not to LambdaCase BlockArguments”?

---

<div class="post-metadata">

### Author: ![enobayram](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/enobayram/32/1815_2.png) [@enobayram](https://discourse.haskell.org/u/enobayram)
#### Post date: [April 21, 2025, 5:53am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/12 "2025-04-21T05:53:30Z")

</div>

I think you folks are missing the primary benefit (or down side, depending on who you ask) of `BlockArguments` here: Avoiding parentheses that are not possible to avoid with `$` (and without contorting your code). For example:

```haskell
findUser >>= mapM \case
  Nothing -> ...
  Just user -> ...

```

Notice how you can’t just insert a `$` after `mapM` here. In general, you must understand that the syntactic role of a “block argument” simply isn’t comparable to `$` having a low precedence. If you’re thinking in terms of precedence, then a block form has an **asymmetric precedence**. I.e. consider `do` as the simplest analogy to `$`. In many cases, you can just replace a `$` with a `do` if you have `BlockArguments`: `putStrLn do "Hello" ++ "World"`, but consider how these are not the same `putStrLn . toUpper $ "Hello" ++ "World"` vs. `putStrLn . toUpper do "Hello" ++ "World"`. Coming back to my asymmetric precedence point: `$` has the lowest precedence, so it binds the last, both to its left hand side (`putStrLn . toUpper`) and to its right hand side (`"Hello" ++ "World"`), but `do` acts as if it has very high precedence on the left hand side (so it binds to `toUpper`), but a very low precedence on the right hand side (So it doesn’t bind to “Hello”).

Another example is:

```haskell
parseAppArgs :: Parser AppArgs
parseAppArgs = AppArgs
  <$> do some . complex $ 
           expression
  <*> do other . complex $
           expressions
  <*> ...

```

In this case, `BlockArguments` is even more magical than just “asymmetric precedence”.

---

<div class="post-metadata">

### Author: ![Liamzy](https://avatars.discourse-cdn.com/v4/letter/l/50afbb/32.png) [@Liamzy](https://discourse.haskell.org/u/Liamzy)
#### Post date: [April 21, 2025, 8:01am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/13 "2025-04-21T08:01:33Z")

</div>

I still remember @maxigit being crazy about this back in the day, is do bulletting now mainstream and considered an essential feature? I recall it was controversial when it was last discussed.

---

<div class="post-metadata">

### Author: ![enobayram](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/enobayram/32/1815_2.png) [@enobayram](https://discourse.haskell.org/u/enobayram)
#### Post date: [April 21, 2025, 8:13am UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/14 "2025-04-21T08:13:09Z")

</div>

I honestly don’t know what the community thinks, but I wouldn’t apologise for using it as in my `parseAppArgs` example above. But then again, I’d probably use `ApplicativeDo` + `RecordWildCards` for that anyway. I reckon that you can go overboard with this stuff, but I don’t feel bad about using syntactic conveniences for making the code clearer.

---

<div class="post-metadata">

### Author: ![Liamzy](https://avatars.discourse-cdn.com/v4/letter/l/50afbb/32.png) [@Liamzy](https://discourse.haskell.org/u/Liamzy)
#### Post date: [April 21, 2025, 4:24pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/15 "2025-04-21T16:24:34Z")

</div>

> [@enobayram](#):
>
> ```haskell
> parseAppArgs :: Parser AppArgs
> parseAppArgs = AppArgs
> <$> do some . complex $ 
> expression
> <*> do other . complex $
> expressions
> <*> ...
> 
> ```

Also, to note, this code actually works without block arguments because the operators are separating the do blocks.

But I can see where you’re coming from, given that I’ve become rather enamored of calling functions with vertical arguments; vertical code is less dense and has more space for inline comments.

---

<div class="post-metadata">

### Author: ![enobayram](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/enobayram/32/1815_2.png) [@enobayram](https://discourse.haskell.org/u/enobayram)
#### Post date: [April 21, 2025, 5:17pm UTC](https://discourse.haskell.org/t/why-not-blockarguments/11885/16 "2025-04-21T17:17:55Z")

</div>

Ha, yeah, good catch 🙂 I was too focused on blocks being more magical than just operator precedence, so didn’t even consider whether this was an example of `BlockArguments`.
