I am having trouble groking F#’s Map class. I created a simple, naive lambda calculus evaluation function,
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'
The obvious optimization to this is to change the list to a Map so I came up with,
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'
Given the values,
let ident = Lam ('x', Var 'x') let prog = App (ident, Lit 3)
why does,
let x = eval(prog, [])
succeed but,
let x2 = eval2(prog, Map [])
throw a key not found exception?
I don’t repro this behavior (using F# 1.9.6.2, it works for me):