我有返回a' option
类型的函数。我的功能看起来像:
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 -> ()
是否有任何功能模式可以避免这种多级match expressions
?
答案 0 :(得分:11)
看起来像你正在寻找的是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
基本上等同于
// ('a -> 'b option) -> 'a option -> 'b option
let bind f m =
match m with
| Some x -> f x
| _ -> None
答案 1 :(得分:4)
函数式编程可以利用monadic操作,特别是bind
运算符。以下是Maybe monad在Haskell上使用的说明,但与F#' s Option
类型相同。
幸运的是,bind
运算符几乎是预定义的:
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
// ...
答案 2 :(得分:0)
另一种选择是为Option类型创建一个Computation Expression Builder,利用Option.bind
函数。
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()
然后,您可以通过一次option
计算完成所有工作:
let foo a =
option {
let! b = fooB a.F1
let! c = fooC b.F2
let! d = fooD c.F3
return! fooE d.F4
}
如果所有选项均为Some
,则会返回d.F4
Some
,否则会返回None
。