2011-06-20 22 views
8

以前の今日は、私は、F#の引用の限界を検出し、ここでそれについて質問を:F#2にMetaOcamlからhttp://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdfに登場する例を変換する際F# quotations: variable may escape scopeF#見積もりの​​別の制限はありますか?

今、私は別の制限が発生している可能性があります。

私はこの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 @>)) @> 

にそれを変換するI以下のコンパイル時にエラーが発生します:2 <@ f @>This expression was expected to have type int -> Expr<int> but here has type Expr<'a>

直感的には、エラーは大変だと思います。しかし、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 @>)) @> 

答えて

4

私はあなたが前の質問と同じ問題に当たっていると思う - 私は紙から必要な宣言をコピーしたとき、私が得た:

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.

これをF#ではスプライスされた式の中で引用符で囲まれた変数をキャプチャすることはできません。これはコードスニペットでは間違いなく行われています。

なぜ別のエラーメッセージが表示されているのか正確にはわかりません。答えることができる最小限の完全なサンプルを投稿できれば、この変数のキャプチャの制限にぶつかります。 (これはおそらくMetaOCamlでかなり使われているものです)。

+0

OK:/私が話していたエラーを生成するコードサンプルを投稿しました。しかし、eval2から複数の行を削除すると、他の質問と同じエラーが出ます:/ –

関連する問題