2015-09-15 11 views
6

मैंने देखा है और इसका जवाब पाने के लिए संघर्ष किया है; मुझे यकीन है कि एक स्पष्ट उत्तर है लेकिन मुझे लगता है कि यह नहीं मिल रहा है; या मैंने उद्धरणों की एक सीमा को मारा है जिसे गणना के अभिव्यक्तियों के साथ उपयोग किए जाने पर मैं पास नहीं कर सकता।गणना अभिव्यक्तियों का उपयोग करके उद्धृत कार्यों को लिखना

मूल रूप से मैं एक गणना F # वर्कफ़्लो का उपयोग करके नीचे उद्धृत लैम्ब्डा के साथ काम करना चाहता हूं। इन वर्कफ़्लो को एक साथ लिखने की कोशिश करते समय समस्या आती है। आदर्श रूप में मैं वर्कफ़्लो < 'एनवी,' परिणाम> उदाहरणों का उपयोग करके एक साथ लिखना चाहता हूं! वाक्य - विन्यास। मेरे कुछ हद तक अनुभवहीन प्रयास नीचे है: "चर" env "एक उद्धरण में बंधे लेकिन एक कटा हुआ अभिव्यक्ति में प्रयोग किया जाता है" जो थोड़े समझ में आता:

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() 

तीसरे बाँध सदस्य मुझे संकलक त्रुटि देता है। सवाल यह है कि मैं इसके आसपास कैसे हो सकता हूं। मैंने ऊपर दिए गए मामलों को काम करने के लिए सरल बनाने की कोशिश करने के प्रयास के रूप में उपरोक्त परिभाषित किया है।

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) 
} 

बस सोच रहा है कि मैं जो हासिल करने की कोशिश कर रहा हूं वह संभव है या क्या मैं कुछ गलत कर रहा हूं? अंतिम उद्धृत अभिव्यक्ति के अंदर उपयोगकर्ता कार्यों को कैप्चर करते समय उपरोक्त सरल मामलों को काम करना संभव है?

संपादित करें: मैंने टॉमस के जवाब को ध्यान में रखते हुए वर्कफ़्लो स्रोत प्रकार के बिना भी कोशिश की है। System.InvalidOperationException:: के साथ त्रुटि फिर भी प्रयास विफल '%' या '%%' के प्रथम श्रेणी का उपयोग करता है Microsoft.FSharp.Core.ExtraTopLevelOperators.SpliceExpression [टी] (FSharpExpr`1 अभिव्यक्ति)

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 @> 
पर की अनुमति नहीं है

उत्तर

2

यह सिर्फ एक विचार का एक स्केच है, लेकिन मुझे लगता है कि आप आगे प्राप्त कर सकते हैं अगर आप कार्यप्रवाह का प्रतिनिधित्व नहीं एक उद्धृत समारोह के रूप में, लेकिन एक समारोह है कि एक उद्धृत पर्यावरण लेता है और एक उद्धृत परिणाम देता है के रूप में:

type Workflow<'Env, 'Result> = Expr<'Env> -> Expr<'Result> 

फिर आप निश्चित रूप से सभी बाध्यों को लागू कर सकते हैं:

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 -> <@ %(selector (workflow %env) env) @> 

कहा, मुझे लगता है यह काफी आप सभी की जरूरत नहीं है - ऐसा लगता है कि संकलक Quote में कोड अनदेखी कर रहा है, तो हम बोली कि Workflow में WorkflowSource बदल जाता जोड़ने भले ही, आप अभी भी त्रुटियों मिलता है क्योंकि वहाँ Expr<WorkflowSource<_>> मान हैं - लेकिन मुझे लगता है कि बांध का एक और अधिभार इसे हल कर सकता है।

member __.Quote(x : Expr<WorkflowSource<_, _>>) : Workflow<_, _> = 
    fun env -> <@ (%x) %env @> 
+1

ऐसा लगता है कि 'Quote' की परिभाषा पूरी तरह से अप्रासंगिक है - संकलक नामित' Quote' एक सदस्य की उपस्थिति के लिए दिखता है juts लेकिन कभी यह आह्वान नहीं करता है (यह सिर्फ की परवाह किए बिना गणना अभिव्यक्ति के शरीर उद्धरण कैसे 'उद्धरण 'लागू किया गया है)। यह बेहद अजीब आईएमओ है, लेकिन इस तरह गणना गणना अभिव्यक्तियां काम करती हैं। – kvb

+0

@kvb हाँ, इस तरह यह मेरी तरफ देखा। बहुत अजीब ... मुझे लगता है कि आप डमी 'उद्धरण' जोड़ सकते हैं और वास्तविक कोड को 'रन' में डाल सकते हैं! –

+0

हां, मुझे विश्वास है कि यह मानक दृष्टिकोण है। – kvb

संबंधित मुद्दे