# 'What are monadic bind and monadic return for C++23 optional?

C++23 `std::optional`

is finally getting some very useful additions.

Since my knowledge of FP is very primitive I am wondering what is the syntax for the following two operations(that according to my googling are 2 basic monadic operations):

- monadic bind
- monadic return

My best guesses are:

monadic bind is transform

monadic return is just C++17 `std::optional`

constructor(8)

## Solution 1:^{[1]}

`mbind`

(it doesn't exist, I'm mimicking Haskell's `>>=`

)

In C++-like pseudo-code, the monadic binding, let's call it `mbind`

, should have such a signature:

```
C<U> mbind(C<T>, std::function<C<U>(T)>);
```

i.e. it should take a monad `C`

on some type `T`

, a function that "pulls * the inside* of that monad out" and turns into a monad

`C`

on a (not necessarily) different type `U`

, `C<U>`

, and gives you back that `C<U>`

.`transform`

(the free one)

The `transform`

you mention, first of all, is a member function, and it has a signature kind of this

```
C<U> C<T>::transform(std::function<U(T)>);
```

but let's rewrite its signature as it would be if it was a free function:

```
C<U> transform(C<T>, std::function<U(T)>);
```

so as you see it takes a `C<T>`

and applies a function from `T`

to `U`

* right inside the functor *, thus resulting in a

`C`

`C<U>`

.## So there's a difference.

To better understand what the difference is, try passing `transform`

a `C<T>`

and a function with signature the one that `mbind`

expects, `std::function<C<U>(T)>`

.

What do you get? Remember that `transform`

applies the function "right inside the functor, without pulling anything out", so you get a `C<C<U>>`

, i.e. one more functorial layer.

`mbind`

, instead, with the same two arguments, would have given you a `C<U>`

.

And how can you go from what `transform(x, f)`

returns to what `mbind(x, f)`

returns, i.e. from a `C<C<U>>`

to a `C<U>`

? You can just flatten/join/collapse/whatever-you-want-to-name-it the two functorial levels, via what's called `join`

in Haskell and `flatten`

in some other language.

Obviously if you can do that (and you can for `C = std::optional`

), then those "functorial layers" were actually "monadic layers".

## So is there an `mbind`

-like thing?

As suggested in the other answer there's the `and_then`

member function.

Is `and_then`

the (non-existing) `mbind`

I've mentioned above? Yes, with the only difference running between them being the same that runs between `transform`

member function and `transform`

free function: one is member and the other is free.(¹)

## And where's `flatten`

/`join`

, by the way?

You might wonder if there's this utility in C++23. I have absolutely no clue, I'm barely aware of what C++20 offers.

However, since the function that makes `std::optional`

a functor is defined as a member function of `std::optional`

itself, I strongly believe that if there was monadic binding function for `std::optional`

, it would be defined as a member function too, and in that case it would be at this page, in the section **Monadic operations**, together with `and_then`

/`transform`

/`or_else`

. Since there isn't, I tend to assume it doesn't exist.

But some knowledge of Haskell helps me give you an idea of why it might be unnecessary to add it to the standard.

What happens if you do this?

```
auto optOfOpt = std::make_optional(std::make_optional(3));
auto whatIsThis = optOfOpt.and_then(std::identity);
```

Yeah, that's it.

(¹) Originally I stressed a bit more on `and_then`

not being `mbind`

because the former is a member function, the latter is a free function.

The reason why I stressed it is that member functions "belong" to classes (in the sense that you can't have a member function without having the class which it is a member of), so in some way the `and_then`

we discuss here is totally unrelated to the namesake function that we'd write to make `std::vector`

a monad, because that would live inside `std::vector`

.

On the other hand, non-member `transform`

and the hypothetical `mbind`

are free functions, so they exist without any need for any class, and so they look a bit more like interfaces to some general abstractions that types can opt in to (like Haskell's type classes). It's clear that, assuming `std::transform`

and `mbind`

were customization point, client code that wants to opt in for some type would have to write a customization for that type, and maybe that could leverage a member function.

Answering to this question made another question pop up in my mind, so I've asked it.

## Solution 2:^{[2]}

Not quite.

In Haskell syntax, bind is of the form `m a -> (a -> m b) -> m b`

, which corresponds to satisfying this concept (for all `A`

, `B`

, `F`

)

```
template <class Fn, class R, class... Args>
concept invocable_r = std::is_invocable_r_v<R, Fn, Args...>;
template <class Bind, template <class> M, class A, class B, invokable_r<M<B>, A> F>
concept bind = invocable_r<Bind, M<B>, M<A>, F>;
```

That's `and_then`

(with `this`

bound to the first argument). `transform`

is fmap (with `this`

bound to the second argument), which is the Functor operation (all Monads are Functors).

`fmap`

is of the form `(a -> b) -> f a -> f b`

.

```
template <class Fmap, template <class> M, class A, class B, invokable_r<B, A> F>
concept fmap = invocable_r<Fmap, M<B>, M<A>, F>;
```

The difference is in the return type of the function being bound or mapped.

Another example of this distinction is .NET's linq `Select`

vs `SelectMany`

Another nitpick is that the monad laws discuss expressions, not statements, so you'd have to wrap the constructor in a function.

## Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution | Source |
---|---|

Solution 1 | |

Solution 2 |