作为计算生成器的对象表达式
给定一个通用的接口声明
type IFoo<'T,'MT> =
abstract Return : 'T -> 'MT
abstract Bind : 'MT * ('T -> 'MT) -> 'MT
实际上可以将对象表达式用作计算构建器表达式,这可以提供一种有趣的方法来分割单向工作流的封装和执行逻辑。
let inline addOption mx my =
{ new IFoo<_,_> with
member __.Return x = Some x
member __.Bind(ma, f) = Option.bind f ma }
{ let! x = mx
let! y = my
return x + y }
// val inline addOption :
// mx: ^a option -> my: ^a option -> ^a option
// when ^a : (static member ( + ) : ^a * ^a -> ^a)
addOption (Some 1) (Some 2)
// val it : int option = Some 3
addOption None (Some 2)
// val it : int option = None
如果预期方法存在,编译器将检查表达式的类型。 但它只是一半; 因为对于真正的monads,我需要获得方法签名abstract Bind : 'MT * ('T -> 'MU) -> 'MU
,这是对不同非封装类型的投影。 为什么不能这样做?