我环顾四周,努力想要得到答案;我确定有一个明显的答案,但我似乎无法找到它;或者我已经达到了与计算表达式一起使用时无法通过的引用限制。
基本上我想使用计算F#工作流程来处理如下定义的lambda。尝试将这些工作流程组合在一起时会出现问题。理想情况下,我想要撰写工作流程<' Env,'结果>实例一起使用let!句法。我有点天真的尝试如下:
<?php
$contents = file('file.scss'); //array with lines from file
$linenum = 0;
foreach($contents as $key=>$line)
{
// a line can start with 0 or more spaces, then // (maybe, maybe not), then 0 or more space, then something entirely unknown, then a : then something entirely unknown and then a ;
//[0] = the whole line [1] = the // or not [2] is the variablename [3] = the variabel value
if (preg_match('/[ ]*([\/]{2})?[ ]*(.*?):(.*?);/is', $line, $matches))
{
$variablename = $matches[2];
$variablevalue = $matches[3];
if ($variablename == '$myvar')
{
if ($matches[1] != '//') //if it is not commented out
$contents[$key] = '$mainColor: red;'; //replace the whole line, if you want to replace only the color you can maybe use str_replace to replace the $variablevalue to something else?
//$contents[$key] = str_replace($variablevalue, 'red', $line); // this line is untested
break;
}
}
}
//do something with the result:
echo implode($contents);
第三个绑定成员给出了编译器错误:&#34;变量&#34; env&#34;在引用中绑定但在切片表达式中使用&#34;哪种有道理。问题是我该如何解决它。我已经将上述内容定义为试图让下面的简单案例起作用。
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()
只是想知道我想要实现的是可能还是我做错了什么?在最终引用的表达式中捕获用户函数时,是否可以使上述简单案例工作?
编辑:我也尝试过没有WorkflowSource类型考虑到Tomas&#39;回答。没有运气仍然有错误:System.InvalidOperationException:头等使用&#39;%&#39;或&#39; %%&#39;是不允许的 在Microsoft.FSharp.Core.ExtraTopLevelOperators.SpliceExpression [T](FSharpExpr`1表达式)
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)
}
答案 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
中的代码,所以即使我们添加引号将WorkflowSource
转换为Workflow
,你仍然会收到错误,因为有Expr<WorkflowSource<_>>
个值 - 但我认为绑定的另一个重载可能会解决这个问题。
member __.Quote(x : Expr<WorkflowSource<_, _>>) : Workflow<_, _> =
fun env -> <@ (%x) %env @>