Buna baktım ve bunun cevabını almak için uğraştım; Eminim bariz bir cevap var ama onu bulamıyorum. veya hesaplama ifadeleriyle kullanıldığında kullanamayacağım bir alıntılama sınırına çarptım.Hesaplama ifadeleri kullanılarak alıntılanmış işlevleri oluşturma
Temel olarak, bir hesaplama F # iş akışı kullanarak aşağıda belirtilen bir alıntı lambda ile çalışmak istiyorum. Bu iş akışlarını birlikte oluşturmaya çalışırken sorun geliyor. İdeal olarak, iş akışını kullanarak Workflow < 'Env,' Sonuç> örneklerini oluşturmak istiyorum! sözdizimi. Benim biraz da naif girişimi aşağıdadır: "değişken 'env' tırnak içinde bağlı ama dilimlenmiş ifadesinde kullanılan" tür mantıklı:
type Workflow<'Env, 'Result> = Expr<'Env -> 'Result>
type WorkflowSource<'Env, 'Result> = 'Env -> 'Result
type WorkflowBuilder() =
member x.Bind
(workflow: WorkflowSource<'Env, 'OldResult>,
selector: 'OldResult -> WorkflowSource<'Env, 'NewResult>) : WorkflowSource<'Env, 'NewResult> =
(fun env -> (selector (workflow env) env))
member x.Bind
(workflow: Workflow<'Env, 'OldResult>,
selector: 'OldResult -> WorkflowSource<'Env, 'NewResult>)
: Workflow<'Env, 'NewResult> =
<@ (fun env -> (selector ((%workflow) env) env)) @>
// This bind is where the trouble is
member x.Bind
(workflow: WorkflowSource<'Env, 'OldResult>,
selector: 'OldResult -> Workflow<'Env, 'NewResult>)
: Workflow<'Env, 'NewResult> =
<@ fun env ->
let newResultWorkflow = %(selector (workflow env))
newResultWorkflow env @>
member __.Return(x) = fun env -> x
member __.ReturnFrom(x : WorkflowSource<_, _>) = x
member __.Quote(x : Expr<WorkflowSource<_, _>>) : Workflow<_, _> = x
let workflow = new WorkflowBuilder()
üçüncü bağlama üyesi bana derleyici hata veriyor. Soru şu ki, etrafımdan nasıl geçebilirim. Yukarıdakileri, basit durumların çalışmasını sağlamaya çalışmak için bir girişim olarak tanımladım.
let getNumber (env: EnvironmentContext) = (new Random()).Next()
let workflow1 = workflow {
let! randomNumber = getNumber
let customValue = randomNumber * 10
return (globalId * customValue)
}
// From expression to non expression bind case
let workflow2a = workflow {
let! workflow1 = workflow1
let! randomNumber = getNumber
return (randomNumber + workflow1)
}
// From non-expression to expression bind case
let workflow2 = workflow {
let! randomNumber = getNumber
let! workflow1 = workflow1
return (randomNumber + workflow1)
}
Sadece ne elde etmek çalışıyorum mümkün olup olmadığını merak veya yanlış bir şey yapıyorum? Son işlem yapılan ifadenin içinde kullanıcı işlevlerini yakalarken yukarıdaki basit vakaları çalışmak mümkün mü?
DÜZENLEME: Ayrıca Tomas'ın yanıtını dikkate alarak WorkflowSource türü olmadan da denedim. System.InvalidOperationException: error ile de başarılı '%' veya %% birinci sınıfı, kullanımları Microsoft.FSharp.Core.ExtraTopLevelOperators.SpliceExpression [T] (FSharpExpr`1 sentezleme)
type WorkflowBuilder() =
member x.Bind
(workflow: Workflow<'Env, 'OldResult>,
selector: 'OldResult -> Workflow<'Env, 'NewResult>)
: Workflow<'Env, 'NewResult> =
fun env -> <@ %(selector (%(workflow env)) env) @>
member __.Return(x) = fun Env -> <@ x @>
member __.ReturnFrom(x: Workflow<_, _>) = x
member __.Quote(expr: Expr<Workflow<'Env, 'Result>>) = expr
// This run method fails
member __.Run(x : Expr<Workflow<'Env, 'Result>>) : Workflow<'Env, 'Result> = fun (env: Expr<'Env>) -> <@ %((%x) env) @>
let workflow = new WorkflowBuilder()
// Env of type int for testing
let getRandomNumber (kernel: Expr<int>) = <@ (new Random()).Next() @>
let workflow1 = workflow {
let! randomNumber = getRandomNumber
let otherValue = 2
let! randomNumber2 = getRandomNumber
return randomNumber + otherValue + randomNumber2
}
// This fails due to quotation slicing issue
workflow1 <@ 0 @>
de izin verilmez
O Quote' 'tanımı tamamen alakasız olduğu ortaya çıktı - derleyici Quote'' adlı bir üyesinin varlığı için görünüyor Arabistan'dan ama Hiç çağırmak değil (sadece bakılmaksızın hesaplama ifadenin vücudunu tırnak Alıntı nasıl uygulanır? Bu son derece garip IMO'dur, ancak hesaplama ifadeleri bu şekilde çalışır. – kvb
@kvb Evet, bana öyle görünüyor. Oldukça garip ... Ben "Alıntı" kukla ekleyebilir ve 'Run' olsa gerçek kodu koyabilirsiniz varsayalım! –
Evet, bunun standart yaklaşım olduğuna inanıyorum. – kvb