Я бы сделал один шаг назад - во-первых, вам нужно выяснить, что такое вычисление, которое вы хотите моделировать. Исходя из того, что вы сказали, вы могли бы сохранить результат со списком некоторого журнала аудита информации:
type Audited<'T> =
{ Log : string list
Result : 'T }
Стандартный базовый расчет строитель будет просто создать пустой журнал в Return
и Bind
просто сцепить журналы:
type AuditBuilder() =
member x.Return(v) = { Log = []; Result = v }
member x.Bind(c, f) =
let fr = f c.Result
{ fr with Log = c.Log @ fr.Log }
let audit = AuditBuilder()
Вы могли бы на самом деле просто использовать это, при условии, что ваша accounts
функция будет возвращать правильное значение Audited<'T>
:
let accounts() =
{ Result = 40
Log = ["accounts"] }
let stocks() =
{ Result = 2
Log = ["stocks"] }
audit {
let! a = accounts()
let! s = stocks()
return a + s }
Теперь вопрос в том, можем ли мы сделать это немного лучше, так что accounts()
не обязательно должна быть специальной функцией. Вы можете сделать это по-разному - но это больше вопрос о создании значений Audited<'T>
сейчас!
Одним из способов сделать что-то подобное было бы передать цитату Bind
. Очень простой и простая реализация выглядит следующим образом:
let plain() = 123
open Microsoft.FSharp.Quotations
type AuditBuilder with
member x.Bind(e:Expr<'T>, f:'T -> _) =
match e with
| Patterns.Call(None, mi, []) ->
let r = f (mi.Invoke(null, [| |]) :?> 'T)
{ r with Log = r.Log @ [mi.Name] }
| _ -> failwith "invalid"
Это добавляет перегруженный Bind
, что позволяет «звонить» в кавычках функция, но она автоматически извлекает имя:
audit {
let! p = <@ plain() @>
return p }
Это все еще нуждается в цитата - я думаю, вы могли бы экспериментировать с другими способами этого, но основная идея заключается в том, что у вас есть базовые вычисления, которые действительно определяют структуру.
вы можете думать о 'f' здесь как о * остальной части рабочего процесса * - так сложно получить это оттуда (это изменится в зависимости от остальной части вашего кода) – Carsten
Что вы пытаетесь сделать с этим ? – Carsten
Да, ваше право f, конечно, продолжение, и я не могу очень сильно, но я застрял :) –