Еще одно ограничение цитат F #? - PullRequest
8 голосов
/ 21 июня 2011

Ранее сегодня я столкнулся с ограничением цитат 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<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 @>)) @>

1 Ответ

4 голосов
/ 21 июня 2011

Я думаю, что вы столкнулись с той же проблемой, что и в предыдущем вопросе - когда я скопировал необходимые декларации из бумаги, я получил:

ошибка FS0446: переменная 'f' связана в кавычке, но используется как часть выражения сращивания. Это недопустимо, так как оно может выйти за рамки.

Это имеет смысл - захват переменных, заключенных в кавычки внутри сращенного выражения, не допускается в F #, и это определенно делается в фрагменте кода.

Я не совсем уверен, почему вы получаете другое сообщение об ошибке - если вы можете опубликовать минимальный законченный образец, то на него можно будет ответить, но вы все равно будете использовать это ограничение захвата переменной. (Что, вероятно, часто используется в MetaOCaml).

...