F#Map麻烦

时间:2009-04-11 18:43:56

标签: f#

我在浏览F#的Map类时遇到了麻烦。我创建了一个简单,天真的lambda演算评估函数,

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"

显而易见的优化是将列表更改为Map,所以我提出了

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 [])

抛出一个未找到密钥的异常?

1 个答案:

答案 0 :(得分:6)

我不重复这种行为(使用F#1.9.6.2,它适用于我):

#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