2011-06-20 26 views
8

El día de hoy me encontré con una limitación de F # citas, e hizo una pregunta acerca de ello aquí: F# quotations: variable may escape scope¿Otra limitación de las citas de F #?

Ahora, puedo haber encontrado otra limitación al convertir ejemplos que aparecen en http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf de MetaOcaml a F #.

este tiempo he MetaOcaml este fragmento:

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>.))>. 

y me convertí a

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 @>)) @> 

me sale el siguiente error de compilación: This expression was expected to have type int -> Expr<int> but here has type Expr<'a> con los dos <@ f @>.

Intuitivamente, creo que el error tiene mucho sentido. ¿Pero hay una manera en F # para describir lo que quiero en este caso?

Ejemplo de código:

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 @>)) @> 

Respuesta

4

Creo que está golpeando el mismo problema que en la pregunta anterior - cuando copié las declaraciones necesarias desde el papel, que tengo:

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.

Este tiene sentido: la captura de variables vinculadas entre comillas dentro de la expresión empalmada no está permitida en F # y esto definitivamente se hace en el fragmento de código.

No estoy muy seguro de por qué está recibiendo un mensaje de error diferente - si puede publicar una muestra completa mínima, se puede responder a esa pregunta, pero de todos modos alcanzará esta limitación de captura variable. (Que es probablemente algo que se usa mucho en MetaOCAMl).

+0

Bien:/He publicado un ejemplo de código que produce el error del que estaba hablando. Sin embargo, si elimino un par de líneas de eval2, obtengo el mismo error que la otra pregunta: / –

Cuestiones relacionadas