F#Map麻烦

chu*_*ckj 2 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"
Run Code Online (Sandbox Code Playgroud)

显而易见的优化是将列表更改为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"
Run Code Online (Sandbox Code Playgroud)

鉴于价值观,

let ident = Lam ("x", Var "x")
let prog = App (ident, Lit 3)
Run Code Online (Sandbox Code Playgroud)

为什么,

let x = eval(prog, [])
Run Code Online (Sandbox Code Playgroud)

成功但是,

let x2 = eval2(prog, Map [])
Run Code Online (Sandbox Code Playgroud)

抛出一个未发现的密钥异常?

Bri*_*ian 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
Run Code Online (Sandbox Code Playgroud)