Reputation: 45295
I have functions which returns a' option
type. And I have functions which looks like:
let foo(a) =
match fooB a.F1 with
| Some(b) -> match fooC b.F2 with
| Some(c) -> match fooD c.F3 with
| Some(d) -> match fooE d.F4 with
// ......
| None -> ()
| None -> ()
| None -> ()
Is there any functional pattern to avoid this multilevel match expressions
?
Upvotes: 2
Views: 117
Reputation: 6510
Another option would be to create an Computation Expression Builder for the Option type, leveraging the Option.bind
function.
type OptionBuilder() =
member __.Bind (opt,map) = Option.bind map opt
member __.Return value = Some value
member __.ReturnFrom (opt: Option<_>) = opt
member __.Zero () = Some ()
let option = OptionBuilder()
Then, you can do all of your work in one option
computation:
let foo a =
option {
let! b = fooB a.F1
let! c = fooC b.F2
let! d = fooD c.F3
return! fooE d.F4
}
This will return Some
of d.F4
if all the Options are Some
, otherwise it will return None
.
Upvotes: 0
Reputation: 101662
Seems like what you're looking for is Option.bind
:
let foo(a) =
fooB a.F1
|> Option.bind(fun b -> fooC b.F2)
|> Option.bind(fun c -> fooD c.F3)
|> Option.bind(fun d -> fooE d.F4)
Option.bind
is basically equivalent to
// ('a -> 'b option) -> 'a option -> 'b option
let bind f m =
match m with
| Some x -> f x
| _ -> None
Upvotes: 11
Reputation: 5741
Functional programming may leverage monadic operations, specifically the bind
operator. Here is an illustration of its use on the Maybe monad, which is from Haskell but does the same as F#'s Option
type.
Luckily, the bind
operator is almost predefined:
let (>>=) ma f = Option.bind f ma
let foo a =
fooB a.F1
>>= fun b -> fooC b.F2
>>= fun c -> fooD c.F3
>>= fun d -> fooE d.F4
// ...
Upvotes: 4