Как получить доступ к значению из Builder с помощью пользовательской операции в выражении вычисления - PullRequest
3 голосов
/ 17 марта 2019

У меня есть Построитель вычислительных выражений, который получает значение во время построения

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
}

Теперь я хотел бы получить доступ к значению e из Вычислительного выражения через пользовательскую операцию, чтобы

buildSome 2 {
    return 1 + e()
}

Итак, я действительно хочу получить доступ к свойствам / значениям в базовом объекте компоновщика и работать с ними

Я думаю, мне нужно что-то вроде

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

, но это не такt работа.

Итак, мой вопрос

a) что-то подобное возможно с использованием пользовательских операций и вычислительных выражений b) и если это возможно, то как?

Отказ от ответственности:
Как обычно в программировании, существует миллион способов достижения подобных эффектов совершенно разными способами.Я явно прошу об этом конкретном способе, и я в порядке, если ответ просто «Нет».Но, пожалуйста, воздержитесь от ответов, которые не являются ответами в самом узком смысле, изложенном здесь.

Ответы [ 2 ]

4 голосов
/ 18 марта 2019

Я не уверен, что вам понравится мой ответ и находится ли он в ваших границах, но вы можете захватить экземпляр компоновщика, используя такой трюк:

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
}
3 голосов
/ 18 марта 2019

Чтобы показать, что первичные аргументы конструктора находятся в области видимости для методов экземпляра компоновщика:

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"

Рассмотрим положение пользовательской операции внутри компоновщика; он будет игнорировать выражения, предшествующие ему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...