Fsharpplus: Why is there no generic 'bind' function?

Created on 31 Oct 2018  路  13Comments  路  Source: fsprojects/FSharpPlus

I know there is the >>= operator to pipe monads, but why is there no free-standing function named bind? So that instead of x >>= f one could write x |> bind x. This is already possible with map (<!> or |>> depending on operator order).

RFC enhancement

Most helpful comment

Personally I don't need it but I don't see any downside of adding it to F#+.

All 13 comments

I think the reason why it wasn't added at the beginning is because in Monads literature, the official name of the function is simply (>>=) and they call it bind (except on Scala world), same thing with applicative 's <*>, but map is a bit different in that there is not really a standard agreed operator, not even a function, since in Haskell and some other languages it's called fmap.

Having said that and now, looking from the F# world:

  • .bind seems to be quite standard in libraries and CEs
  • .map as well, some projects (like this one and FParsec) use also the |>> operator, while <!> seems to have a wider adoption, although it's semantics are more tied to Applicatives that Functors.
  • .apply seems to be used frequently for <*>

So, I think your question reveals a valid discussion, could you summarize what would be the main benefit of having a generic bind available, in place of just using (=<<) ?

More readable for non-FP-heads, and lower "WTF factor" when finding out the standard and expected bind function doesn't exist. :)

In the case when you'd browse the API using intellisense, it does makes sense to have bind defined. However, in parts of the library, Identity.fs#L18 they are defined differently than you'd expect from a bind (they are static members in order for this to work). You could expose the functions with f# signature in modules.

There's a lot of "trickery" in this library that I don't understand, but isn't bind defined this as easy shown below?

f# let inline bind = (=<<)

I think I misunderstood what it was you wanted. Then it sounds like something that could be implemented in a single pull request, see for instance:
https://github.com/fsprojects/FSharpPlus/blob/v1.0.0/src/FSharpPlus/Operators.fs#L72-L76
i.e. you would get

f# /// Takes a function from a plain type to a monadic value and a monadic value, and returns a new monadic value. let inline bind (f:'T->'``Monad<'U>``) (x:'``Monad<'T>``) :'``Monad<'U>`` = Bind.Invoke x f

Great! To be clear, I'm after this usage (lame example, but I hope the usage is clear):

f# Some 2 |> map Some |> bind id // we're back to Some 2

isn't that join ?

bind id is join yes, but I'm after bind in itself and that degenerate example was the first that came to mind.

Here's another:

```f#
type Person = { Name: string option }

tryGetPerson ()
|> bind (fun p -> p.Name)
```

I'm sort of in favor of it, since it allows you to use the generic version with the explicit name. Perhaps @cannorin has any insights?

I don't see why it should not be in the library. Since the library already has map as a generic alternative to Option.map, List.map etc., it should also have bind as an alternative to Option.bind etc. :)

Personally I don't need it but I don't see any downside of adding it to F#+.

Same comment as @cannorin and yes, the definition is basically that, but you need to add explicit parameters as values cannot be inlines.

So, if everybody agrees, feel free to PR

Already did #194

Just quick and dirty, feel free to improve or discard, I've no need to own this change

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cmeeren picture cmeeren  路  9Comments

ShalokShalom picture ShalokShalom  路  4Comments

btrepp picture btrepp  路  3Comments

abelbraaksma picture abelbraaksma  路  3Comments

cmeeren picture cmeeren  路  7Comments