debugMinor
Doing an ROP style bind for two functions on the same input in a pipeline
Viewed 0 times
samethedoinginputstyletwoforropbindfunctions
Problem
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
Please let me know how I would achieve what I want in an idiomatic style.
Here's my code. All above
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 =
| Success of 'S
| Failure of message : 'F list
let bind f x =
match x with
| Success s -> f s
| Failure f -> Failure f
let bind2 (f1 : 'A -> Result)
(f2 : 'A -> Result) (x : Result) : Result =
match x with
| Success _ ->
let r1, r2 = (bind f1) x, (bind f2) x
match r1, r2 with
| Success s1, Success s2 ->
Success(s1, s2)
| Failure f1, _ ->
Failure f1
| _, Failure f2 ->
Failure f2
| Failure f -> Failure f
let demo1 (a: int) : Result =
Success a
let demo2 (a: int) : Result =
a |> string |> Success
let demo3 (a: int) : Result =
a |> (*) -1 |> string |> Success
let demo4 (s1 : string, s2 : string) =
sprintf "%s - %s" s1 s2 |> Success
let Demo =
bind demo1
>> bind2 demo2 demo3
>> bind demo4Solution
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.
which you can then use like so
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)Code Snippets
type DemoBuilder() =
member x.Bind(m,f) = bind f m
member x.Return(s) = Success s
let demo = DemoBuilder()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)Context
StackExchange Code Review Q#142054, answer score: 8
Revisions (0)
No revisions yet.