Las*_*olt 8 f# metaprogramming multi-stage-programming metaocaml
今天早些时候我遇到了F#报价的限制,并在这里问了一个问题:F#报价:变量可能会逃避范围
现在,在将MetaOcaml中出现的http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf中的示例转换为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>.))>.
Run Code Online (Sandbox Code Playgroud)
我把它转换成了
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 @>)) @>
Run Code Online (Sandbox Code Playgroud)
我得到以下编译时错误:This expression was expected to have type int -> Expr<int> but here has type 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 @>)) @>
Run Code Online (Sandbox Code Playgroud)
我认为您遇到了与上一个问题相同的问题 - 当我从论文中复制必要的声明时,我得到:
错误 FS0446:变量“f”绑定在引号中,但用作拼接表达式的一部分。这是不允许的,因为它可能超出其范围。
这是有道理的 - F# 中不允许捕获在拼接表达式内的引号中绑定的变量,而这肯定是在代码片段中完成的。
我不太确定为什么你会收到不同的错误消息 - 如果你可以发布一个最小的完整示例,那么就可以回答这个问题,但你仍然会遇到这个变量捕获限制。(这可能是 MetaOCaml 中经常使用的东西)。