ceth
ceth

Reputation: 45295

How to rewrite multi-level match expression

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

Answers (3)

Aaron M. Eshbach
Aaron M. Eshbach

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

JLRishe
JLRishe

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

kaefer
kaefer

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

Related Questions