Reputation: 33395
The F# Option type is a good way to return 'result or failure' from a function.
Sometimes you need to chain such functions, along the lines of:
Of course this can be done with pattern matching; an actual code fragment from a function that is itself implementing pattern matching in this way:
match mtch env a0 a1 with
|Some env->
mtch env b0 b1
|None->
None
But it feels like there should be a more compact way to express this common idiom, perhaps with a higher order function. Is there something like that?
Upvotes: 2
Views: 1008
Reputation: 960
You could use Computation Expressions. I'll use an example found on this page: https://fsharpforfunandprofit.com/posts/computation-expressions-intro/
Create the computation:
type MaybeBuilder() =
member _.Bind(x, f) =
match x with
| None -> None
| Some a -> f a
member _.Return(x) =
Some x
let maybe = new MaybeBuilder()
An example function that returns an Option:
let divideBy bottom top =
if bottom = 0
then None
else Some(top/bottom)
A workflow using the Computation and chaining divideBy:
let divideByWorkflow init x y z =
maybe{
let! a = init |> divideBy x
let! b = a |> divideBy y
let! c = b |> divideBy z
return c
}
Usage examples:
let good = divideByWorkflow 12 3 2 1 //Some 2
let bad = divideByWorkflow 12 3 0 1 //None
Upvotes: 4
Reputation: 5741
There's an Option
module in FSharp.Core, providing "basic operations on options." Specifically, the signature of Option.bind
matches your use case:
binder:('T -> 'U option) -> option:'T option -> 'U option
It states in the VisualStudio pop-up hint that bind f inp evaluates to match inp with None -> None | Some x -> f x.
// The actual argument values are not important here
let env, a0, a1, b0, b1 = (), (), (), (), ()
let mtch env _ _ = Some env // or might be None
match mtch env a0 a1 with
|Some env -> mtch env b0 b1
|None -> None
mtch env a0 a1
|> Option.bind (fun env -> mtch env b0 b1)
You might even improve on that by defining custom operators for operations on options.
let (>>=) ma f = Option.bind f ma
let (>>.) ma f = Option.map f ma
mtch env a0 a1
>>= fun env -> mtch env b0 b1
>>= ...
Upvotes: 6