Hi! First time on the Zulip, so not sure if this has been proposed already. I _love_ the ! syntax for backpassing / don't-call-it-a-monad for Tasks! However, I think it would be pretty sweet to be able to use that syntax in other cases where you want similar monadic semantics, for example (I've done both of these in Haskell and loved the simplicity):
Random generators
Assuming Random a : Seed -> (Seed, a), it should be possible to implement an andThen function for Random with the signature Random a -> (a -> Random b) -> Random b which should enable the following syntax:
randomPerson : Random { first : Str, last : Str, age : U8 }
randomPerson =
first = Random.str!
last = Random.str!
age = Random.u8!
{ first, last, age }
Parsers
Similarly, an andThen should be possible, just with Parser a instead of Random a:
bencodedInt =
Parse.char! 'i'
digits = Parse.digits!
Parse.char! 'e'
Str.toU64 digits
Skipping over a lot of details, of course, but compared to e.g. how randomness and parsing was done in Elm, the ! syntax would bring something as simple as Haskell's do notation.
Welcome @Daniel Schierbeck,
Richard has discussed this before.
Just to give a concise update here.
Backpassing <- is deprecated and being removed.
So no more first <- Random.str |> Random.andThen
The current plan is that roc will introduce shadowing.
Shadowing will support things like this.
(first, state) = Random.str state
(last, state) = Random.str state
(age, state) = Random.u8 state
{ first, last, age }
If that isn't enough, we will consider expanding ! or alternative solution, but that is not planned currently.
As an extra note, I think record builder syntax could actually be perfect for this, right @Agus Zubiaga?
Don't actually know what the exact syntax would be and #ideas > map2-based record builders is changing the syntax anyway.
Random.thread state
{
first: <- Random.str
last: <- Random.str
age: <- Random.u8
}
So @Daniel Schierbeck since the language is still in flux (syntax, std lib, etc.), we add and remove things as we try them out and see how much value they add. If after updating record builders and adding ! and ? syntax sugar we still find there's a lot of code that would be cleaner with backpassing, we'd be open to adding it back in! It's just unlikely since it's consistently the hardest thing for newcomers to grasp in the language.
@Brendan Hansknecht thanks for the reply! I guess shadowing would improve things quite a lot, but it would still be much more of a hassle to write code like that. I guess a dedicated Result operator would be broadly useful for e.g. writing input validations, and would obviate _some_ of the need for an extensible solution such as allowing custom implementations of a monad-like type class (not suggesting allowing custom classes, just custom implementations). But it _is_ still way more of a hassle than an imperative language would afford, I think. But good to hear that you're iterating! ! is definitely easier to grok that <- :grinning:
@Sam Mohr I also found backpassing difficult to use
yeah... I'm surprised that Gleam has committed to it over a ? or alternatives for result handling and what not
I think Louis Pilford's (the Gleam language BDFL) logic is that a simple tool that can handle everything is better than having multiple, specialized tools
An otherwise very good language, no hate here
Very much a "platform versus product" tradeoff
Last updated: Jun 16 2026 at 16:19 UTC