Recently I discovered a style of programming which is very useful (and pretty) in functional world called Railway oriented programming. For example when want to create a pipeline of functions that produce option type, and we want to return None if any of them fails we can do something like this:
someOptionValue // : 'a option
>>= func1 // func1: 'a -> 'b option
>>= func2 // func2: 'b -> 'c option
and so on...
where (>>=) : 'a option -> (a' -> 'b option) -> 'b option
operator applies a value to the left hands side if it's Some value
or None
otherwise.
But, here is my problem, what if we have a function that "takes" two (or many) option types, let say funcAB : 'a -> 'b -> 'c option
, valA : 'a option
and valB : 'b option
and we still want to create this pipeline or use some nice operator (not create a new one specifically for this, but use some standard approach, in particular I don't want to use match ... with
to "unpack" option values)
Currently I have something like this:
valA
>>= (funcAB >> Some)
>>= (fun ctr -> valB >>= ctr)
But is doesn't seem 'correct' (or fun is the better word ;] ), and it doesn't scale well if a function takes more parameters or we want to create a longer pipeline. Is there a better way to do this?
I've used F# syntax but I think this question can be applied to any functional programming language, like OCaml and Haskell.
EDIT (Solution):
Thanks to the chi's answer I've created following code F# which is much more idiomatic then what I previously had:
funcAB <!> valA <*> valB |> Option.flatten
And it looks well if we have more values: funcAB <!> valA <*> valB <*> valC <*> ...
.
I've used operators defined in YoLo.