# Looking around for a monad for dealing with early "return"

**URL:** https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356
**Category:** Ecosystem
**Tags:** monad
**Created:** [July 14, 2026, 10:47pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356 "2026-07-14T22:47:48Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 14, 2026, 10:47pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/1 "2026-07-14T22:47:48Z")

</div>

As with a lot of things, I think I know how to write this, but I figured I’d ask around, b/c I can’t find it by googling, and perhaps somebody here knows where to look.

I’m translating some Python code to OCaml, and it’s going really well. But I have come across a function that has a complex if-then-else tree, followed by another. And in the first, there are some "return"s. Now I think I know how to write a monad to capture this, and I’m going to go ahead and do that, but I figured I’d ask if anybody here had any suggestions for where to look ?

The type of the monad would be something like:

```auto
type ('continue_ty, 'ret_ty) = Continue of 'continue_ty | Return of 'ret_ty

```

and the idea is that a piece of code that returns `Continue x` expects the next bit of code to be executed, on `x`.

Also, I wondered if there was a “bestiary” of OCaml monad implementations … that might be useful to have.

Thanks in advance.

ETA: Ah, I can just use an exception to implement the early-return. I’ll do that!

---

<div class="post-metadata">

### Author: ![hummy123](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hummy123/32/4558_2.png) [@hummy123](https://discuss.ocaml.org/u/hummy123)
#### Post date: [July 14, 2026, 11:20pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/2 "2026-07-14T23:20:17Z")

</div>

Exceptions will probably make your code most direct-style and easiest to follow, like you pointed out.

I think the closest I know to a pre-existing monad for what you want is the `result` type, and the `Result.bind` function, although I’m not sure if it fits your use case since the two cases are `Ok` and `Error`, when it seems like `Error` is a state you don’t want to model (or which isn’t possible) in your example type.

> **[OCaml library : Result](https://ocaml.org/manual/5.5/api/Result.html)**

---

<div class="post-metadata">

### Author: ![pyx](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pyx/32/5162_2.png) [@pyx](https://discuss.ocaml.org/u/pyx)
#### Post date: [July 14, 2026, 11:50pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/3 "2026-07-14T23:50:02Z")

</div>

You can use local exception:

```auto
let exception Exit in
try ...
with Exit ->

```

Nice and clean.

A bare-bone early exit monad could be:

```auto
module Pipeline = struct
  type ('a, 'b) t = Continue of 'a | Terminal of 'b

  let pure v = Continue v
  let exit v = Terminal v

  let bind m f =
    match m with
    | Continue x -> f x
    | Terminal x as value -> value

  module Syntax = struct let ( let* ) = bind end
  module Infix = struct let ( >>= ) = bind end
end

```

But it’s just a Result monad in disguise…

---

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 15, 2026, 12:19am UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/4 "2026-07-15T00:19:21Z")

</div>

Honestly, I’m surprised at myself that I didn’t just reach for exceptions for nonlocal exit and `ref` for the updatable variables from the jump, not bothering to post to ask the question. Too much time spent hacking in pure functional OCaml.

---

<div class="post-metadata">

### Author: ![pyx](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pyx/32/5162_2.png) [@pyx](https://discuss.ocaml.org/u/pyx)
#### Post date: [July 15, 2026, 12:39am UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/5 "2026-07-15T00:39:33Z")

</div>

You don’t even need `ref`:

```auto
let exception Exit of int in
try raise (Exit 42)
with Exit c -> c

```

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [July 15, 2026, 12:41am UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/6 "2026-07-15T00:41:25Z")

</div>

> [@Chet\_Murthy](#):
>
> Also, I wondered if there was a “bestiary” of OCaml monad implementations … that might be useful to have.

The most extensive collection of algebraic computational structures in OCaml I’m aware of is @xvw’s [preface](https://github.com/xvw/preface#available-abstractions-in-make-and-specs).

---

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 15, 2026, 12:51am UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/7 "2026-07-15T00:51:49Z")

</div>

haha yes, that’s what I did:

```auto

let rec _closure self input (config : AC.t) configs ~currentAltReachedAcceptState
          ~speculative ~treatEofAsEpsilon =
  let exception EarlyReturn of bool in
  let currentAltReachedAcceptState = ref currentAltReachedAcceptState in
  try
      .... raise (EarlyReturn true) ....
  with
    EarlyReturn rv -> rv

```

The `ref` is for the one variable that is imperatively modified in the interesting control-flow nest.

---

<div class="post-metadata">

### Author: ![eWert-Online](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ewert-online/32/4130_2.png) [@eWert-Online](https://discuss.ocaml.org/u/eWert-Online)
#### Post date: [July 15, 2026, 12:59pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/8 "2026-07-15T12:59:46Z")

</div>

This also exists in JaneStreet’s base library:

> **[base v0.17.3 · OCaml Package](https://ocaml.org/p/base/v0.17.3/doc/base/Base/With_return/index.html)**
>
> base v0.17.3: Full standard library replacement for OCaml

---

<div class="post-metadata">

### Author: ![bmourad01](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bmourad01/32/4629_2.png) [@bmourad01](https://discuss.ocaml.org/u/bmourad01)
#### Post date: [July 15, 2026, 3:21pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/9 "2026-07-15T15:21:08Z")

</div>

I’m reminded of this PR that was submitted to BAP a while back: [rewrites knowledge and primus monads by ivg · Pull Request #1361 · BinaryAnalysisPlatform/bap · GitHub](https://github.com/BinaryAnalysisPlatform/bap/pull/1361)

The “double-barreled” CPS style here seems like a nice, general way to accomplish this.

---

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 15, 2026, 5:58pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/10 "2026-07-15T17:58:41Z")

</div>

Aha, very nice! I am reminded of … John Reppy writing this sort of CPS transformer back in the late 80s as part of SML/NJ. Two continuations, one the normal continuation, one the exception continuation.

---

<div class="post-metadata">

### Author: ![hummy123](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hummy123/32/4558_2.png) [@hummy123](https://discuss.ocaml.org/u/hummy123)
#### Post date: [July 15, 2026, 9:00pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/11 "2026-07-15T21:00:41Z")

</div>

I thought Andrew Kennedy came up with the double-barrelled CPS idea and terminology in his “Compiling with Continuations, Continued” paper, but it’s interesting that the idea apparently predates that paper by two decades!

I think I probably misremembered the credit from this article, which cites Andrew Kennedy’s paper as an influence for using double-barrelled CPS is OCaml, but that’s only where they got the idea from and not where the idea itself originated.

> **[Flambda2 Ep. 1: Foundational Design Decisions](https://ocamlpro.com/blog/2024_03_19_the_flambda2_snippets_1/)**
>
> Welcome to The Flambda2 Snippets! In this first post of The Flambda2 Snippets, we dive into the powerful CPS-based internal representation used within the Flambda2 optimizer, which was one of the main motivation to move on from the former Flambda...

---

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 16, 2026, 3:33pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/12 "2026-07-16T15:33:59Z")

</div>

I became a caml-light fan back in 1991 when I realized that SML/NJ was fatally greedy of computer resources, and it really mattered. And I’ve written about how complete was my conversion before. So …

I suspect that every possible CPS-like thingie that we can imagine (other than, well, state-passing) has already been done in the SML/NJ corpus somewhere. B/c it was central to the implementation of that system, eh?

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [July 16, 2026, 5:41pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/13 "2026-07-16T17:41:28Z")

</div>

> [@Chet\_Murthy](#):
>
> I’ve written about how complete was my conversion before.

I think that must be at [What are your feelings about : mlton,mosml,polyml,smlnj - #5 by Chet\_Murthy](https://discuss.ocaml.org/t/what-are-your-feelings-about-mlton-mosml-polyml-smlnj/9901/5) ? I love reading this history 🙂

---

<div class="post-metadata">

### Author: ![amongonz](https://avatars.discourse-cdn.com/v4/letter/a/a88e4f/32.png) [@amongonz](https://discuss.ocaml.org/u/amongonz)
#### Post date: [July 17, 2026, 10:25am UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/14 "2026-07-17T10:25:18Z")

</div>

For anyone looking at Base.With\_return for reference:

> It is only because of a deficiency of ML types that **`with_return`** doesn’t have type:
> 
> ```auto
> val with_return : 'a. (('a -> ('b. 'b)) -> 'a) -> 'a 
> 
> ```

OCaml 5.5 is there now, it can type `: 'a. (('b. 'a -> 'b) -> 'a) -> 'a` which works just as well here.

---

<div class="post-metadata">

### Author: ![VPhantom](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/vphantom/32/1396_2.png) [@VPhantom](https://discuss.ocaml.org/u/VPhantom)
#### Post date: [July 20, 2026, 3:23pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/15 "2026-07-20T15:23:52Z")

</div>

FYI for local exceptions you probably don’t want the overhead of the stack trace, so that’d be `raise_notrace …`

---

<div class="post-metadata">

### Author: ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)
#### Post date: [July 20, 2026, 3:35pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/16 "2026-07-20T15:35:22Z")

</div>

Maybe I’d remembered this tidbiit in some back corner of the cache … but if so it got swapped out to disk and later to tape long ago. Thank you for pulling it back into main memory!

---

<div class="post-metadata">

### Author: ![pyx](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pyx/32/5162_2.png) [@pyx](https://discuss.ocaml.org/u/pyx)
#### Post date: [July 21, 2026, 4:22pm UTC](https://discuss.ocaml.org/t/looking-around-for-a-monad-for-dealing-with-early-return/18356/17 "2026-07-21T16:22:01Z")

</div>

I used monad for this kind of logic almost all the time, and personally prefer point-free style[1], so I never pay attention to this, today I learned something new, thanks.

[1]:

```ocaml
let* res = do_foo m >>= do_bar >>= do_baz in
....
(* or using Kleisli composition *)
let pipeline = do_foo >=> do_bar >=> do_baz

```
