Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 使用计算表达式组合引用函数_F#_Quotations_Computation Expression - Fatal编程技术网

F# 使用计算表达式组合引用函数

F# 使用计算表达式组合引用函数,f#,quotations,computation-expression,F#,Quotations,Computation Expression,我环顾四周,努力寻找答案;我肯定有一个显而易见的答案,但我就是找不到;或者我遇到了引用的限制,当与计算表达式一起使用时,我无法通过引用 基本上,我想使用一个计算F#工作流处理一个引用的lambda,定义如下。当尝试将这些工作流组合在一起时会出现问题。理想情况下,我希望使用let将工作流实例组合在一起!语法。我有点天真的尝试如下: type Workflow<'Env, 'Result> = Expr<'Env -> 'Result> type WorkflowSou

我环顾四周,努力寻找答案;我肯定有一个显而易见的答案,但我就是找不到;或者我遇到了引用的限制,当与计算表达式一起使用时,我无法通过引用

基本上,我想使用一个计算F#工作流处理一个引用的lambda,定义如下。当尝试将这些工作流组合在一起时会出现问题。理想情况下,我希望使用let将工作流实例组合在一起!语法。我有点天真的尝试如下:

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()
只是想知道我正在努力实现的是可能的还是我做错了什么?在捕获最终引用表达式中的用户函数时,是否可以使上述简单情况正常工作

编辑:考虑到Tomas的答案,我也尝试了不使用WorkflowSource类型。仍有错误:System.InvalidOperationException:不允许使用“%”或“%”的第一类 在Microsoft.FSharp.Core.ExtraTopLevelOperators.剪接表达式[T](FSharpExpr`1表达式)中

键入WorkflowBuilder()=
成员x.绑定
(工作流:工作流,
选择器:“旧结果->工作流)
:工作流=
趣味环境->
成员返回(x)=乐趣环境->
成员_uu.ReturnFrom(x:Workflow)=x
成员(expr:expr)=expr
//此运行方法失败

成员_uu.Run(x:Expr):Workflow=fun(env:Expr这只是一个想法的草图,但我认为如果您将工作流表示为一个引用函数,而不是一个引用环境并返回一个引用结果的函数,则可以更进一步:

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

事实证明,
Quote
的定义是完全不相关的-编译器突出查找名为
Quote
的成员的存在,但从不调用它(无论
Quote
如何实现,它只引用计算表达式的主体)。这在我看来非常奇怪,但这就是计算表达式的工作方式。@kvb是的,在我看来就是这样。非常奇怪……我想你可以添加虚拟的
引号
,然后将实际代码放入
运行
中!是的,我相信这是标准的方法。谢谢大家的建议。编辑我的原始帖子以纳入acccount尝试。仍有错误,但至少有三个计算表达式进行了编译检查。作为更新,无论我如何努力,都会遇到此特定错误:System.InvalidOperationException:不允许使用第一类“%”或“%”。我认为这种想法也行不通。计算表达式的quote方法Pression builder为我提供了一个Expr>,我无法解决如何解包回工作流的问题,即在运行时不出现上述错误的Expr。在编译上述检查时考虑这个想法,至少在我目前对报价的了解下,可能不起作用。
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 @>
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) @>
member __.Quote(x : Expr<WorkflowSource<_, _>>) : Workflow<_, _> = 
  fun env -> <@ (%x) %env @>