代码之家  ›  专栏  ›  技术社区  ›  chuckj

F图故障

f#
  •  2
  • chuckj  · 技术社区  · 15 年前

    我在摸索F的地图课上遇到了麻烦。我创建了一个简单、简单的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"
    

    对此的明显优化是将列表更改为一个映射,因此我提出,

    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 回复  |  直到 15 年前
        1
  •  6
  •   Brian    15 年前

    我不谴责这种行为(使用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