如何在自定义Computation Expression中实现let! ... and! ...语法
let! ... and!是F# 6引入的并行绑定语法,你可以通过两种路径实现该特性支持,两种方案的签名和实现示例如下:
方法签名说明
- 方案一:
MergeSources+ 已有Bind实现(推荐,可支持2个以上的and!绑定)MergeSources签名:member _.MergeSources: Foo<'T> * Foo<'U> -> Foo<'T * 'U>,作用是将两个计算上下文合并为一个包含二元组的新计算上下文- 无需额外实现
Bind2,配合你已经完成的普通Bind方法即可正常工作
- 方案二:直接实现
Bind2(仅支持最多2个并行绑定,性能无额外开销)Bind2签名:member _.Bind2: Foo<'T> * Foo<'U> * ('T * 'U -> Foo<'V>) -> Foo<'V>,作用是直接接收两个计算上下文和后续处理函数,完成绑定逻辑
实现示例
我们以Option类型的foo计算表达式为例给出可运行的实现:
type FooBuilder() = // 基础必备实现:Return member _.Return(x: 'T) : 'T option = Some x // 常规Bind实现,用于普通let!语法 member _.Bind(m: 'T option, f: 'T -> 'U option) : 'U option = Option.map f m |> Option.join // 方案一实现:MergeSources,支持多个and!绑定 member _.MergeSources(m1: 'T option, m2: 'U option) : ('T * 'U) option = match m1, m2 with | Some x, Some y -> Some (x, y) | _ -> None // 方案二可选实现(可替换方案一):仅支持单个and!的Bind2 // member _.Bind2(m1: 'T option, m2: 'U option, f: 'T * 'U -> 'V option) : 'V option = // match m1, m2 with // | Some x, Some y -> f (x, y) // | _ -> None // 实例化计算表达式构建器 let foo = FooBuilder()
你提问中的示例代码运行结果如下:
let f = foo { let! x = foo { return 1 } and! y = foo { return 2 } return x + y } // 输出结果为 Some 3 printfn "%A" f
如果需要支持3个及以上的并行绑定(比如let! a = ... and! b = ... and! c = ...),选择实现MergeSources的方案即可,编译器会自动重复调用MergeSources两两合并所有绑定的计算上下文。
内容的提问来源于stack exchange,提问作者sdgfsdh
相关产品推荐
相关产品推荐

