;; 这将导致 val i-6ren">
gpt4 book ai didi

f# - 为 "roughly"相同的代码引用生成不同的表达式

转载 作者:行者123 更新时间:2023-12-04 23:16:49 25 4
gpt4 key购买 nike

给定以下类型

type Foo = { foo: string; bar: int };;

以及以下代码引用
<@fun v x -> { x with foo = v; bar = 99 } @>;;

这将导致
val it : Quotations.Expr<(string -> Foo -> Foo)> =
Lambda (v, Lambda (x, NewRecord (Foo, v, Value (99))))

这是预期的。还有下面的代码引用
<@fun v x -> { x with bar = v;foo = "foo" } @>;;

产生预期的结果。
val it : Quotations.Expr<(int -> Foo -> Foo)> =
Lambda (v, Lambda (x, NewRecord (Foo, Value ("foo"), v)))

但是,这(更改顺序 将值分配给第二个字段)
<@fun v x -> { x with bar = 66;foo = v } @>;;

产量
val it : Quotations.Expr<(string -> Foo -> Foo)> =
Lambda (v, Lambda (x, Let (bar, Value (66), NewRecord (Foo, v, bar))))
let .但是没有 let在代码中。为什么是这样?

最佳答案

引用仅保证它们将生成具有正确行为的表达式,而不是任何特定形状。

例如报价<@@ 1 = 2 || 2 = 3 @@>将生成一个包含 if 的表达式声明(即 if 1 = 2 then true else 2 = 3 )。

对结果表达式进行规范化是一个非常深的兔子洞,但您可以在这里看到一些基本的规范化器:https://github.com/mavnn/Algebra.Boolean/blob/master/Algebra.Boolean/Transforms.fs

具体请查unbind在文件的末尾。

let unbind quote =
let rec findLet q =
match q with
| Let (var, value, body) ->
findLet (replaceVar var.Name value body)
| ShapeLambda (v, e) ->
Expr.Lambda(v, findLet e)
| ShapeVar v ->
Expr.Var v
| ShapeCombination (o, es) ->
RebuildShapeCombination(o, es |> List.map findLet)
and replaceVar name value q =
match q with
| Let (v, e, e') ->
if v.Name = name then
findLet (Expr.Let(v, e, e'))
else
Expr.Let(v, replaceVar name value e, replaceVar name value e')
| ShapeLambda (v, e) ->
Expr.Lambda(v, replaceVar name value e)
| ShapeVar v ->
if v.Name = name then
value
else
Expr.Var v
| ShapeCombination (o, es) ->
RebuildShapeCombination(o, es |> List.map (replaceVar name value))
findLet quote

至于为什么这些具体的表达方式不同?不知道,我害怕!

关于f# - 为 "roughly"相同的代码引用生成不同的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39124594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com