2009-04-11 12 views
2

F#のマップクラスを苦労しています。私は値を考えると、単純な、素朴なラムダ計算の評価関数、F#Map Trouble

type Name = string 
type Term = 
    | Var of Name 
    | Lit of int 
    | App of Term * Term 
    | Lam of Name * Term 

let rec lookup(v, e) = 
    match e with 
    | (v1, t)::tl   -> if v1 = v then t else lookup(v, tl) 
    | []     -> failwith "unknown variable %s" v 

let rec eval(x, e) = 
    match x with 
    | Var x    -> lookup(x, e) 
    | Lit x    -> Lit x 
    | App (Lam(v, f), t2) -> eval(f, ((v, t2)::e)) 
    | _     -> failwith "Invalid" 

これには明らかな最適化は、私が思いついた地図のリストを変更することで、

let rec eval2(x, e: Map<Name,Term>) = 
    match x with 
    | Var v    -> e.[v] 
    | Lit l    -> x 
    | App (Lam (v, f), t) -> eval2(f, e.Add(v, t)) 
    | _     -> failwith "Invalid term" 

を作成し、

let ident = Lam ("x", Var "x") 
let prog = App (ident, Lit 3) 

なぜ、

let x = eval(prog, []) 

は成功したが、

let x2 = eval2(prog, Map []) 

は、鍵が見つからない例外をスロー?

答えて

6

私は(それが私の作品、F#の1.9.6.2を使用して)、この動作をREPROません:

#light 

type Name = string 
type Term = 
    | Var of Name 
    | Lit of int 
    | App of Term * Term 
    | Lam of Name * Term 

let rec eval2(x, e: Map<Name,Term>) = 
    match x with 
    | Var v    -> e.[v] 
    | Lit l    -> x 
    | App (Lam (v, f), t) -> eval2(f, e.Add(v, t)) 
    | _     -> failwith "Invalid term" 

let ident = Lam ("x", Var "x") 
let prog = App (ident, Lit 3) 
let x2 = eval2(prog, Map []) 
printfn "%A" x2 // Lit 3 
+0

うーん。さて、VSを閉じて再オープンした後も、それを再現することはできません。 – chuckj