Skip to content

Commit 86db7ee

Browse files
committed
힘드니 밀어 소스 추가
1 parent d035041 commit 86db7ee

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

Diff for: sbestudy/nephilim/chap16/.HindleyMilner.scala.swp

24 KB
Binary file not shown.

Diff for: sbestudy/nephilim/chap16/HindleyMilner.scala

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package chap16
2+
3+
abstract class Term {}
4+
5+
case class Var(x:String) extends Term {
6+
override def toString = x;
7+
}
8+
9+
case class Lam(x:String, e:Term) extends Term {
10+
override def toString = "(\\" + x + "." + e + ")"
11+
}
12+
13+
case class App(f:Term, e:Term) extends Term {
14+
override def toString = "(" + f + " " + e + ")"
15+
}
16+
17+
case class Let(x:String, e:Term, f:Term) extends Term {
18+
override def toString = "let " + x + " = " + e + " in " + f
19+
}
20+
21+
sealed abstract class Type {}
22+
case class Tyvar(a:String) extends Type {
23+
override def toString = a
24+
}
25+
26+
case class Arrow(t1:Type, t2:Type) extends Type {
27+
override def toString = "(" + t1 + "->" + t2 + ")"
28+
}
29+
30+
case class Tycon(k:String, ts:List[Type]) extends Type {
31+
override def toString = k + (if (ts.isEmpty) "" else ts.mkString("[",",","]"))
32+
}
33+
34+
object typeInfer {
35+
private var n:Int = 0
36+
def newTyvar():Type = { n += 1; Tyvar("a" + n) }
37+
38+
abstract class Subst extends Function1[Type, Type] {
39+
def lookup(x:Tyvar):Type
40+
41+
def apply(t:Type):Type = t match {
42+
case tv@Tyvar(a) => val u = lookup(tv); if ( u == t ) t else apply(u)
43+
case Arrow(t1,t2) => Arrow(apply(t1), apply(t2))
44+
case Tycon(k, ts) => Tycon(k, ts map apply)
45+
}
46+
47+
def extend(x:Tyvar, t:Type) = new Subst {
48+
def lookup( y: Tyvar ):Type = if ( x==y ) t else Subst.this.lookup(y)
49+
}
50+
}
51+
52+
val emptySubst = new Subst { def lookup(t:Tyvar):Type = t }
53+
54+
case class TypeScheme(tyvars:List[Tyvar], tpe:Type) {
55+
def newInstance: Type = {
56+
(emptySubst /: tyvars) ((s,tv) => s.extend(tv, typeInfer.newTyvar())) (tpe)
57+
}
58+
}
59+
60+
type Env = List[ (String, TypeScheme) ]
61+
def lookup(env: Env, x:String): TypeScheme = env match {
62+
case List() => null
63+
case (y,t) :: env1 => if ( x== y) t else lookup(env1, x)
64+
}
65+
66+
def tyvars(t:Type):List[Tyvar] = t match {
67+
case tv@Tyvar(a) => List(tv)
68+
case Arrow(t1,t2) => tyvars(t1) union tyvars(t2)
69+
case Tycon(k,ts) => (List[Tyvar]() /: ts) ((tvs, t) => tvs union tyvars(t))
70+
}
71+
72+
//scala> tyvars(Tyvar("a"))
73+
//res6: List[Tyvar] = List(a)
74+
//scala> tyvars(Arrow(Tyvar("a"),Tycon("b",List(Tyvar("c"),Tyvar("d")))) )
75+
//res11: List[Tyvar] = List(a, c, d)
76+
77+
def tyvars(ts:TypeScheme): List[Tyvar] =
78+
tyvars(ts.tpe) diff ts.tyvars
79+
80+
def tyvars(env:Env):List[Tyvar] =
81+
(List[Tyvar]() /: env) ( (tvs, nt) => tvs union tyvars(nt._2))
82+
83+
def gen( env:Env, t:Type): TypeScheme =
84+
TypeScheme(tyvars(t) diff tyvars(env), t)
85+
86+
case class TypeError(s: String) extends Exception(s) {}
87+
88+
def mgu(t: Type, u: Type, s: Subst): Subst = (s(t), s(u)) match {
89+
case (Tyvar(a), Tyvar(b)) if (a == b) => s
90+
case (Tyvar(a), _) if !(tyvars(u) contains a) => s.extend(Tyvar(a), u)
91+
case (_, Tyvar(a)) => mgu(u, t, s)
92+
case (Arrow(t1, t2), Arrow(u1, u2)) => mgu(t1, u1, mgu(t2, u2, s))
93+
case (Tycon(k1, ts), Tycon(k2, us)) if (k1 == k2) =>
94+
(s /: (ts zip us)) ((s, tu) => mgu(tu._1, tu._2, s))
95+
case _ => throw new TypeError("cannot unify " + s(t) + " with " + s(u))
96+
}
97+
98+
def tp(env: Env, e: Term, t: Type, s: Subst): Subst = {
99+
current = e
100+
e match {
101+
case Var(x) => {
102+
val u = lookup(env, x)
103+
if (u == null) throw new TypeError("undefined: " + x)
104+
else mgu(u.newInstance, t, s)
105+
}
106+
case Lam(x, e1) => {
107+
val a, b = newTyvar()
108+
val s1 = mgu(t, Arrow(a, b), s)
109+
val env1 = (x, TypeScheme(List(), a)) :: env
110+
tp(env1, e1, b, s1)
111+
}
112+
case App(e1, e2) =>
113+
{
114+
val a = newTyvar()
115+
val s1 = tp(env, e1, Arrow(a, t), s)
116+
tp(env, e2, a, s1)
117+
}
118+
case Let(x, e1, e2) =>
119+
{
120+
val a = newTyvar()
121+
val s1 = tp(env, e1, a, s)
122+
tp((x, gen(env, s1(a))) :: env, e2, t, s1)
123+
}
124+
}}
125+
var current: Term = null
126+
def typeOf(env: Env, e: Term): Type = {
127+
val a = newTyvar()
128+
tp(env, e, a, emptySubst)(a)
129+
}
130+
}
131+
132+
133+
object predefined {
134+
val booleanType = Tycon("Boolean", List())
135+
val intType = Tycon("Int", List())
136+
def listType(t: Type) = Tycon("List", List(t))
137+
private def gen(t: Type): typeInfer.TypeScheme = typeInfer.gen(List(), t)
138+
private val a = typeInfer.newTyvar()
139+
val env = List(
140+
("true", gen(booleanType)),
141+
("false", gen(booleanType)),
142+
("if", gen(Arrow(booleanType, Arrow(a, Arrow(a, a))))),
143+
("zero", gen(intType)), ("succ", gen(Arrow(intType, intType))),
144+
("nil", gen(listType(a))),
145+
("cons", gen(Arrow(a, Arrow(listType(a), listType(a))))),
146+
("isEmpty", gen(Arrow(listType(a), booleanType))),
147+
("head", gen(Arrow(listType(a), a))),
148+
("tail", gen(Arrow(listType(a), listType(a)))),
149+
("fix", gen(Arrow(Arrow(a, a), a)))
150+
)
151+
}
152+
153+
object testInfer {
154+
def showType(e: Term): String =
155+
try {
156+
typeInfer.typeOf(predefined.env, e).toString
157+
} catch {
158+
case typeInfer.TypeError(msg) =>
159+
"\n cannot type: " + typeInfer.current +
160+
"\n reason: " + msg
161+
}
162+
}
163+
164+
165+

0 commit comments

Comments
 (0)