Doing an ROP style bind for two functions on the same input in a pipeline I am working on understanding Railway Oriented Programming (Scott Wlaschin style) in F#.  In my example I want to create a pipeline which does some calculation, applies two different functions to the output of that initial calculation, then hands off a tuple of its results to a final function.

In real code the 'initial calculation' might be getting some data, the 'two different functions' might produce a textual summary and a chart of the data, and the final function might be rendering some output containing both the text and the chart.

I've invented a bind2 function to achieve this, but I can't help thinking that if this was a good idea it would already be common practice and must appear (in disguise) in existing libraries such as Scott's.

Please let me know how I would achieve what I want in an idiomatic style.

Here's my code.  All above bind2 is taken broadly from Scott's code, the remainder is my bind2 function and a simple demo.

type Result&lt;'S, 'F&gt; =
| Success of 'S
| Failure of message : 'F list

let bind f x = 
    match x with 
    | Success s -&gt; f s
    | Failure f -&gt; Failure f

let bind2 (f1 : 'A -&gt; Result&lt;'B, 'F&gt;)
          (f2 : 'A -&gt; Result&lt;'C, 'F&gt;) (x : Result&lt;'A, 'F&gt;) : Result&lt;'B * 'C, 'F&gt; =
    match x with
    | Success _ -&gt;
        let r1, r2 = (bind f1) x, (bind f2) x
        match r1, r2 with
        | Success s1, Success s2 -&gt;
            Success(s1, s2)
        | Failure f1, _ -&gt;
            Failure f1
        | _, Failure f2 -&gt;
            Failure f2
    | Failure f -&gt; Failure f

let demo1 (a: int) : Result&lt;int, string&gt; =
    Success a

let demo2 (a: int) : Result&lt;string, string&gt; =
    a |&gt; string |&gt; Success

let demo3 (a: int) : Result&lt;string, string&gt; =
    a |&gt; (*) -1 |&gt; string |&gt; Success

let demo4 (s1 : string, s2 : string) =
    sprintf "%s - %s" s1 s2 |&gt; Success

let Demo =
    bind demo1
    &gt;&gt; bind2 demo2 demo3
    &gt;&gt; bind demo4
I actually wouldn't bother defining a bind2 as this can lead to an explosion, bind3, 4, 5, 6. Instead I would define a simple computation builder to do this. So using your code from above. 

 type DemoBuilder() = 
     member x.Bind(m,f) = bind f m
     member x.Return(s) = Success s

 let demo = DemoBuilder()


which you can then use like so 

 let DemoB x = 
    demo {
        let! input = x
        let! a = demo1 input
        let! b = demo2 a
        let! c = demo3 a
        return (b,c)
    }

 DemoB (Success 1)