如何在计算表达式中使用自定义操作从构建器访问值

How to Access a Value from a Builder using Custom Operation in a Computation Expression

我有一个计算表达式生成器,它接收 构造期间的值

type SomeBuilder<'e> (e: 'e) =
    member this.Bind(x, fn) = ...
    member this.Return x  = ...
    member this.ReturnFrom x = ...

let buildSome v = SomeBuilder(v)

buildSome 2 {
    return 1
}

现在我想从 通过自定义操作的计算表达式

buildSome 2 {
    return 1 + e()
}

所以我真的很想访问底层构建器对象中的 properties/values 并使用它们

我想我需要这样的东西

type SomeBuilder<'e> (e: 'e) =
    member this.Bind(x, fn) = ...
    member this.Return x  = ...
    member this.ReturnFrom x = ...
    [<CustomOperation("e")>]
    member this.E () = e        

但这不起作用。

所以我的问题是

a) 使用 CustomOperations 和 Computational Expressions 是可能的 b) 如果可能的话,怎么做?

免责声明:
像往常一样,在编程中有一百万种方法可以达到类似的效果 以完全不同的方式。我明确要求这种特殊方式 如果答案只是 "No",我也可以。但请避免回答此处列出的最狭义的非答案。

我不确定您是否会喜欢我的回答以及它是否在您的范围内,但您可以使用如下技巧捕获构建器实例:

type SomeBuilder<'e> (e: 'e) =
    member this.Value = e

    [<CustomOperation("extract", MaintainsVariableSpaceUsingBind = true, AllowIntoPattern = true)>]
    member this.Extract (state) = this

    member this.Bind(x, fn) = fn x
    member this.Return x  = x
    member this.ReturnFrom x = x


let builder e = new SomeBuilder<_>(e)

let x = builder 1 {
    extract into builder // now we've brought builder in the scope
    printfn "here we can read the value = %d" builder.Value
    return 0
}

表明主构造函数参数在构建器实例方法的范围内:

type SomeBuilder<'e> (e: 'e) =
    member __.Bind(x, fn) = fn x
    member __.Return x = x
    [<CustomOperation("e", MaintainsVariableSpaceUsingBind = true,  AllowIntoPattern = true)>]
    member __.E _ = e

SomeBuilder 2 {
    e into i
    return 1 + i }
// val it : int = 3
SomeBuilder "bar" {
    e into s
    return "foo" + s }
// val it : string = "foobar"

考虑自定义操作在构建器内部的位置;它会忽略它前面的表达式。