F# 引用的另一个限制?

发布于 2024-11-16 11:45:15 字数 2875 浏览 1 评论 0原文

今天早些时候,我遇到了 F# 引用的限制,并在这里提出了一个问题:F# 引用: 变量可能转义作用域

现在,我在转换 http://www.cs.rice.edu/~taha/publications/ Journal/dspg04a.pdf 从 MetaOcaml 到 F#。

这次我有这个 MetaOcaml 片段:

let rec peval2 p env fenv=
    match p with
    Program ([],e) -> eval2 e env fenv
    | Program (Declaration (s1,s2,e1)::tl,e) ->
         .<let rec f x = .~(eval2 e1 (ext env s2 .<x>.)
                                     (ext fenv s1 .<f>.))
           in .~(peval2 (Program(tl,e)) env (ext fenv s1 .<f>.))>.

并将其转换为

let rec peval2 p env fenv =
    match p with
    | Program ([], e) -> eval2 e env fenv
    | Program (Declaration (s1, s2, e1) :: tl, e) ->
        <@ let rec f x = %(eval2 e1 (ext env s2 <@ x @>)
                                    (ext fenv s1 <@ f @>))
           in %(peval2 (Program(tl, e)) env (ext fenv s1 <@ f @>)) @>

以下编译时错误: This expression was Expected to have type int ->表达但这里有类型 Expr<'a> 和两个 <@ f @>

直觉上,我认为这个错误很有意义。但是 F# 有没有办法描述我在这种情况下想要的东西?

代码示例:

open Microsoft.FSharp.Quotations

type Exp =
    | Int of int
    | Var of string
    | App of string * Exp
    | Add of Exp * Exp
    | Sub of Exp * Exp
    | Mul of Exp * Exp
    | Div of Exp * Exp
    | Ifz of Exp * Exp * Exp

type Def = Declaration of string * string * Exp
type Prog = Program of Def list * Exp

exception Yikes

let env0 = fun x -> raise Yikes

let fenv0 = env0

let ext env x v = fun y -> if x = y then v else env y

let rec eval2 e env fenv =
    match e with
    | Int i -> <@ i @>
    | Var s -> env s
    | App (s, e2) -> <@ %(fenv s) %(eval2 e2 env fenv) @>
    | Add (e1, e2) -> <@ %(eval2 e1 env fenv) + %(eval2 e2 env fenv) @>
    | Sub (e1, e2) -> <@ %(eval2 e1 env fenv) - %(eval2 e2 env fenv) @>
    | Mul (e1, e2) -> <@ %(eval2 e1 env fenv) * %(eval2 e2 env fenv) @>
    | Div (e1, e2) -> <@ %(eval2 e1 env fenv) / %(eval2 e2 env fenv) @>
    | Ifz (e1, e2, e3) -> <@ if %(eval2 e1 env fenv) = 0
                             then %(eval2 e2 env fenv)
                             else %(eval2 e3 env fenv) @>

let rec peval2 p env fenv =
    match p with
    | Program ([], e) -> eval2 e env fenv
    | Program (Declaration (s1, s2, e1) :: tl, e) ->
        <@ let rec f x = %(eval2 e1 (ext env s2 <@ x @>)
                                    (ext fenv s1 <@ f @>))
           in %(peval2 (Program(tl, e)) env (ext fenv s1 <@ f @>)) @>

Earlier today I encountered a limitation of F# quotations, and asked a question about it here: F# quotations: variable may escape scope

Now, I may have encountered another limitation when converting examples appearing in http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf from MetaOcaml to F#.

This time I've this MetaOcaml snippet:

let rec peval2 p env fenv=
    match p with
    Program ([],e) -> eval2 e env fenv
    | Program (Declaration (s1,s2,e1)::tl,e) ->
         .<let rec f x = .~(eval2 e1 (ext env s2 .<x>.)
                                     (ext fenv s1 .<f>.))
           in .~(peval2 (Program(tl,e)) env (ext fenv s1 .<f>.))>.

and I converted it to

let rec peval2 p env fenv =
    match p with
    | Program ([], e) -> eval2 e env fenv
    | Program (Declaration (s1, s2, e1) :: tl, e) ->
        <@ let rec f x = %(eval2 e1 (ext env s2 <@ x @>)
                                    (ext fenv s1 <@ f @>))
           in %(peval2 (Program(tl, e)) env (ext fenv s1 <@ f @>)) @>

I get the following compile-time error: This expression was expected to have type int -> Expr<int> but here has type Expr<'a> with the two <@ f @>.

Intuitively, I think the error makes a lot of sense. But is there a way in F# to describe what I want in this case?

Code sample:

open Microsoft.FSharp.Quotations

type Exp =
    | Int of int
    | Var of string
    | App of string * Exp
    | Add of Exp * Exp
    | Sub of Exp * Exp
    | Mul of Exp * Exp
    | Div of Exp * Exp
    | Ifz of Exp * Exp * Exp

type Def = Declaration of string * string * Exp
type Prog = Program of Def list * Exp

exception Yikes

let env0 = fun x -> raise Yikes

let fenv0 = env0

let ext env x v = fun y -> if x = y then v else env y

let rec eval2 e env fenv =
    match e with
    | Int i -> <@ i @>
    | Var s -> env s
    | App (s, e2) -> <@ %(fenv s) %(eval2 e2 env fenv) @>
    | Add (e1, e2) -> <@ %(eval2 e1 env fenv) + %(eval2 e2 env fenv) @>
    | Sub (e1, e2) -> <@ %(eval2 e1 env fenv) - %(eval2 e2 env fenv) @>
    | Mul (e1, e2) -> <@ %(eval2 e1 env fenv) * %(eval2 e2 env fenv) @>
    | Div (e1, e2) -> <@ %(eval2 e1 env fenv) / %(eval2 e2 env fenv) @>
    | Ifz (e1, e2, e3) -> <@ if %(eval2 e1 env fenv) = 0
                             then %(eval2 e2 env fenv)
                             else %(eval2 e3 env fenv) @>

let rec peval2 p env fenv =
    match p with
    | Program ([], e) -> eval2 e env fenv
    | Program (Declaration (s1, s2, e1) :: tl, e) ->
        <@ let rec f x = %(eval2 e1 (ext env s2 <@ x @>)
                                    (ext fenv s1 <@ f @>))
           in %(peval2 (Program(tl, e)) env (ext fenv s1 <@ f @>)) @>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

演出会有结束 2024-11-23 11:45:15

我认为您遇到了与上一个问题相同的问题 - 当我从论文中复制必要的声明时,我得到:

错误 FS0446:变量“f”绑定在引号中,但用作拼接表达式的一部分。这是不允许的,因为它可能会超出其范围。

这是有道理的 - F# 中不允许捕获在拼接表达式内的引号中绑定的变量,而这肯定是在代码片段中完成的。

我不太确定为什么你会收到不同的错误消息 - 如果你可以发布一个最小的完整示例,那么就可以回答这个问题,但你仍然会遇到这个变量捕获限制。 (这可能是 MetaOCaml 中经常使用的东西)。

I think you're hitting the same problem as in the previous question - when I copied the necessary declarations from the paper, I got:

error FS0446: The variable 'f' is bound in a quotation but is used as part of a spliced expression. This is not permitted since it may escape its scope.

This makes sense - capturing variables bound in quotation inside spliced expression is not allowed in F# and this is definitely done in the code snippet.

I'm not exactly sure why you're getting a different error messagae - if you can post a minimal complete sample, than that can be answered, but you'll still going to hit this variable capture limitation. (Which is probably something that's used quite a lot in MetaOCaml).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文