1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
/** Cleaned up in october 2010 by paulp.
* Hey, we should get this working.
*/
// Class hierarchy
trait Term[a]
object Var{ def unapply[a](x:Var[a]) = Some(x.name) }
class Var[a] (val name : String) extends Term[a]
object Num{ def unapply(x:Num) = Some(x.value) }
class Num (val value : Int) extends Term[Int]
object Lam{ def unapply[b,c](l: Lam[b,c]) = Some(l.x, l.e) }
class Lam[b, c](val x : Var[b], val e : Term[c]) extends Term[b => c]
object App{ def unapply[b,c](a: App[b,c]) = Some(a.f, a.e) }
class App[b, c] (val f : Term[b => c], val e : Term[b]) extends Term[c]
object Suc { def unapply(a: Suc) = true }
class Suc() extends Term[Int => Int]
// Environments :
abstract class Env {
def apply[a](v: Var[a]): a
def extend[a](v: Var[a], x : a) = new Env {
def apply[b](w: Var[b]): b = w match {
case _ : v.type => x // v eq w, hence a = b
case _ => Env.this.apply(w)
}}
}
object empty extends Env {
def apply[a](x: Var[a]): a = throw new Error("not found : "+x.name)
}
object Test {
val v1 = new Var[util.Random]("random")
val v2 = new Var[Int]("Int")
val v3 = new Var[List[String]]("list")
val anEnv = (empty
.extend(v1, new util.Random)
.extend(v2, 58)
.extend(v3, Nil)
)
def eval[a](t: Term[a], env : Env): a = t match {
// First three work
case v : Var[b] => env(v) // a = b
case n @ Num(value) => value // a = Int
case a @ App(f,e) => eval(f, env)(eval(e, env)) // a = c
// Next one fails like:
//
// found : (Int) => Int
// required: a
case i @ Suc() => { (y: Int) => y + 1 } // a = Int => Int
// Next one fails like:
//
// error: '=>' expected but '[' found.
// case f @ Lam[b,c](x, e) => { (y: b) => eval(e, env.extend(x, y)) } // a = b=>c
// ^
case f @ Lam[b,c](x, e) => { (y: b) => eval(e, env.extend(x, y)) } // a = b=>c
}
val f1 = () => eval(v1, anEnv)
val f2 = () => eval(v2, anEnv)
val f3 = () => eval(v3, anEnv)
def main(args: Array[String]): Unit = {
println(f1())
println(f2())
println(f3())
}
}
|