给出类似
的通用接口声明type IFoo<'T,'MT> =
abstract Return : 'T -> 'MT
abstract Bind : 'MT * ('T -> 'MT) -> 'MT
实际上可以使用对象表达式作为计算构建器表达式,这可以为monadic工作流的封装和执行逻辑之间的划分提供一种有趣的方法。
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
如果存在预期的方法,编译器会检查表达式的类型。但它只有一半;因为对于真正的monad,我需要获得方法签名abstract Bind : 'MT * ('T -> 'MU) -> 'MU
,这是对不同非封装类型的投影。为什么不能这样做?