summaryrefslogtreecommitdiff
path: root/sources/examples
diff options
context:
space:
mode:
Diffstat (limited to 'sources/examples')
-rw-r--r--sources/examples/fors.scala63
-rw-r--r--sources/examples/iterators.scala12
-rw-r--r--sources/examples/maps.scala152
-rw-r--r--sources/examples/parsers.scala53
-rw-r--r--sources/examples/parsers1.scala115
-rw-r--r--sources/examples/patterns.scala28
-rw-r--r--sources/examples/sort.scala27
-rw-r--r--sources/examples/sort1.scala12
-rw-r--r--sources/examples/sort2.scala12
-rw-r--r--sources/examples/typeinf.scala162
10 files changed, 636 insertions, 0 deletions
diff --git a/sources/examples/fors.scala b/sources/examples/fors.scala
new file mode 100644
index 0000000000..55849f4010
--- /dev/null
+++ b/sources/examples/fors.scala
@@ -0,0 +1,63 @@
+module fors {
+
+ trait Person {
+ val name: String;
+ val age: Int;
+ }
+
+ def printOlderThan20(xs: Seq[Person]): Iterator[String] =
+ printOlderThan20(xs.elements);
+
+ def printOlderThan20(xs: Iterator[Person]): Iterator[String] =
+ for (val p <- xs; p.age > 20) yield p.name;
+
+ def divisors(n: Int): List[Int] =
+ for (val i <- List.range(1, n); n % i == 0) yield i;
+
+ def isPrime(n: Int) = divisors(n).length == 2;
+
+ def findNums(n: Int): Iterator[Pair[Int, Int]] =
+ for (val i <- Iterator.range(1, n);
+ val j <- Iterator.range(1, i-1);
+ isPrime(i+j)) yield Pair(i, j);
+
+ def sum(xs: List[Double]): Double =
+ (0.0 foldl_: xs) { (x, y) => x + y }
+
+ def scalProd(xs: List[Double], ys: List[Double]) =
+ sum(for(val Pair(x, y) <- xs zip ys) yield x * y);
+
+ type Lst = List[Any];
+
+ val books = List(
+ 'book('title("Structure and Interpretation of Computer Programs"),
+ 'author("Abelson, Harald"),
+ 'author("Sussman, Gerald J.")),
+ 'book('title("Principles of Compiler Design"),
+ 'author("Aho, Alfred"),
+ 'author("Ullman, Jeffrey")),
+ 'book('title("Programming in Modula-2"),
+ 'author("Wirth, Niklaus")));
+
+ def findAuthor(books: Lst) =
+ for (val 'book(book: Lst) <- books;
+ val 'title(title: String) <- book;
+ (title indexOf "Program") >= 0;
+ val 'author(author: String) <- book) yield author;
+
+ for (val 'book(b: Lst) <- books;
+ val 'author(author: String) <- b;
+ author startsWith "Ullman";
+ val 'title(title: String) <- b) yield title;
+
+ removeDuplicates(
+ for (val 'book(b1: Lst) <- books;
+ val 'book(b2: Lst) <- books;
+ b1 != b2;
+ val 'author(a1: String) <- b1;
+ val 'author(a2: String) <- b2;
+ a1 == a2) yield Pair(a1, a2));
+
+ def removeDuplicates[a](xs: List[a]): List[a] =
+ xs.head :: removeDuplicates(for (val x <- xs.tail; x != xs.head) yield x)
+}
diff --git a/sources/examples/iterators.scala b/sources/examples/iterators.scala
new file mode 100644
index 0000000000..8eae9fb026
--- /dev/null
+++ b/sources/examples/iterators.scala
@@ -0,0 +1,12 @@
+module iterators {
+
+ def printArray(xs: Array[Int]) =
+ Iterator.fromArray(xs) foreach (x => System.out.println(x));
+
+ def findGreater(xs: Array[Double], limit: Double) =
+ Iterator.fromArray(xs)
+ .zip(Iterator.from(0))
+ .filter{case Pair(x, i) => x > limit}
+ .map{case Pair(x, i) => i}
+
+}
diff --git a/sources/examples/maps.scala b/sources/examples/maps.scala
new file mode 100644
index 0000000000..3e75049765
--- /dev/null
+++ b/sources/examples/maps.scala
@@ -0,0 +1,152 @@
+module maps {
+
+ trait MapStruct[kt, vt] {
+ trait Map extends Function1[kt, vt] with {
+ def extend(key: kt, value: vt): Map;
+ def remove(key: kt): Map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ type map <: Map;
+ val empty: map;
+ }
+
+ class AlgBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = AlgMap;
+
+ val empty: AlgMap = Empty();
+
+ private case class
+ Empty() extends AlgMap {},
+ Node(key: kt, value: vt, l: map, r: map) extends AlgMap {}
+
+ trait AlgMap extends Map {
+ def apply(key: kt): vt = this match {
+ case Empty() => null
+ case Node(k, v, l, r) =>
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v
+ }
+
+ def extend(key: kt, value: vt): map = this match {
+ case Empty()=> Node(key, value, empty, empty)
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.extend(key, value), r)
+ else if (key > k) Node(k, v, l, r.extend(key, value))
+ else Node(k, value, l, r)
+ }
+
+ def remove(key: kt): map = this match {
+ case Empty()=> empty
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.remove(key), r)
+ else if (key > k) Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ Node(midKey, r.apply(midKey), l, r.remove(midKey))
+ }
+ }
+
+ def domain: Stream[kt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.domain append Stream.cons(k, r.domain)
+ }
+
+ def range: Stream[vt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.range append Stream.cons(v, r.range)
+ }
+ }
+ }
+
+ class OOBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = OOMap;
+
+ trait OOMap extends Map with {
+ def apply(key: kt): vt;
+ def extend(key: kt, value: vt): map;
+ def remove(key: kt): map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ module empty extends OOMap with {
+ def apply(key: kt): vt = null;
+ def extend(key: kt, value: vt) = new Node(key, value, empty, empty);
+ def remove(key: kt) = empty;
+ def domain: Stream[kt] = Stream.empty;
+ def range: Stream[vt] = Stream.empty;
+ }
+ private class Node(k: kt, v: vt, l: map, r: map) extends OOMap with {
+ def apply(key: kt): vt =
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+ def extend(key: kt, value: vt): map =
+ if (key < k) new Node(k, v, l.extend(key, value), r)
+ else if (key > k) new Node(k, v, l, r.extend(key, value))
+ else new Node(k, value, l, r);
+ def remove(key: kt): map =
+ if (key < k) new Node(k, v, l.remove(key), r)
+ else if (key > k) new Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ new Node(midKey, r(midKey), l, r.remove(midKey))
+ }
+ def domain: Stream[kt] = l.domain append Stream.cons(k, r.domain);
+ def range: Stream[vt] = l.range append Stream.cons(v, r.range);
+ }
+ }
+
+ class MutBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = MutMap;
+ class MutMap(key: kt, value: vt) extends Map with {
+ val k = key;
+ var v = value;
+ var l = empty, r = empty;
+
+ def apply(key: kt): vt =
+ if (this == empty) null
+ else if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+
+ def extend(key: kt, value: vt): map =
+ if (this == empty) new MutMap(key, value)
+ else {
+ if (key < k) l = l.extend(key, value)
+ else if (key > k) r = r.extend(key, value)
+ else v = value;
+ this
+ }
+
+ def remove(key: kt): map =
+ if (this == empty) this
+ else if (key < k) { l = l.remove(key) ; this }
+ else if (key > k) { r = r.remove(key) ; this }
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ var mid = r;
+ while (!(mid.l == empty)) { mid = mid.l }
+ mid.r = r.remove(mid.k);
+ mid.l = l;
+ mid
+ }
+ def domain: Stream[kt] =
+ if (this == empty) Stream.empty;
+ else l.domain append Stream.cons(k, r.domain);
+ def range: Stream[vt] =
+ if (this == empty) Stream.empty;
+ else l.range append Stream.cons(v, r.range);
+ }
+ val empty = new MutMap(null, null);
+ }
+}
+
+
+
diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala
new file mode 100644
index 0000000000..43a386e8db
--- /dev/null
+++ b/sources/examples/parsers.scala
@@ -0,0 +1,53 @@
+package examples;
+
+module Parse {
+
+ type Result = Option[List[Char]];
+
+ trait Parser extends Function1[List[Char],Result] with {
+ def &&& (def p: Parser) = new Parser {
+ def apply(in: List[Char]) = Parser.this.apply(in) match {
+ case Some(in1) => p(in1)
+ case n => n
+ }
+ }
+
+ def ||| (def p: Parser) = new Parser {
+ def apply(in: List[Char]) = Parser.this.apply(in) match {
+ case None() => p(in)
+ case s => s
+ }
+ }
+ }
+
+ val empty = new Parser { def apply(in: List[Char]): Result = Some(in) }
+
+ def fail = new Parser { def apply(in: List[Char]): Result = None() }
+
+ def chrWith(p: Char => Boolean) = new Parser {
+ def apply(in: List[Char]): Result = in match {
+ case List() => None()
+ case (c :: in1) => if (p(c)) Some(in1) else None()
+ }
+ }
+
+ def chr(c: Char): Parser = chrWith(d => d == c);
+
+ def opt(p: Parser): Parser = p ||| empty;
+ def rep(p: Parser): Parser = opt(rep1(p));
+ def rep1(p: Parser): Parser = p &&& rep(p);
+}
+
+module ExprParser {
+ import Parse._;
+
+ def letter = chrWith(c => c.isLetter);
+ def digit = chrWith(c => c.isDigit);
+
+ def ident = letter &&& rep(letter ||| digit);
+ def number = digit &&& rep(digit);
+
+ def expr:Parser = expr1 &&& rep((chr('+') &&& expr1) ||| (chr('-') &&& expr1));
+ def expr1 = expr2 &&& rep((chr('*') &&& expr2) ||| (chr('/') &&& expr2));
+ def expr2 = ident ||| number ||| (chr('(') &&& expr &&& chr(')'));
+}
diff --git a/sources/examples/parsers1.scala b/sources/examples/parsers1.scala
new file mode 100644
index 0000000000..cf2d02d076
--- /dev/null
+++ b/sources/examples/parsers1.scala
@@ -0,0 +1,115 @@
+package examples;
+
+trait Tree {}
+case class Var(n: String) : Tree extends Tree {}
+case class Num(n: Int) : Tree extends Tree {}
+case class Binop(op: Char, l: Tree, r: Tree): Tree extends Tree {}
+
+module Parse {
+
+ type Result[b] = Option[Pair[b, List[Char]]];
+
+ trait Parser[p] extends Function1[List[Char], Result[p]] {
+
+ def apply(in: List[Char]): Result[p];
+
+ def filter(p: p => Boolean) = new Parser[p] {
+ def apply(in: List[Char]): Result[p] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => if (p(x)) Some(Pair(x, in1)) else None()
+ case n => n
+ }
+ }
+
+ def map[b](f: p => b) = new Parser[b] {
+ def apply(in: List[Char]): Result[b] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
+ case None() => None()
+ }
+ }
+
+ def flatMap[b](f: p => Parser[b]) = new Parser[b] {
+ def apply(in: List[Char]): Result[b] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => f(x)(in1)
+ case None() => None()
+ }
+ }
+
+ def ||| (def p: Parser[p]) = new Parser[p] {
+ def apply(in: List[Char]): Result[p] = Parser.this.apply(in) match {
+ case None() => p(in)
+ case s => s
+ }
+ }
+
+ def &&& [b](def p: Parser[b]): Parser[b] =
+ for (val _ <- this; val result <- p) yield result;
+ }
+
+ def succeed[p](x: p) = new Parser[p] {
+ def apply(in: List[Char]) = Some(Pair(x, in))
+ }
+
+ def rep[a](p: Parser[a]): Parser[List[a]] =
+ rep1(p) ||| succeed(List());
+
+ def rep1[a](p: Parser[a]): Parser[List[a]] =
+ for (val x <- p; val xs <- rep(p)) yield x :: xs;
+
+ def opt[a](p: Parser[a]): Parser[Option[a]] =
+ (for (val x <- p) yield Some(x): Option[a]) ||| succeed(None(): Option[a]);
+}
+
+
+module ExprParser {
+ import Parse._;
+
+ def chrWith(p: Char => Boolean) = new Parser[Char] {
+ def apply(in: List[Char]): Result[Char] = in match {
+ case List() => None()
+ case (c :: in1) => if (p(c)) Some(Pair(c, in1)) else None()
+ }
+ }
+
+ def chr(c: Char): Parser[Char] = chrWith(d => d == c);
+
+ def letter: Parser[Char] = chrWith(c => c.isLetter);
+ def digit : Parser[Char] = chrWith(c => c.isDigit);
+
+ def ident: Parser[String] =
+ for (val c <- letter; val cs <- rep(letter ||| digit))
+ yield ((c :: cs) foldr "") {(c, s) => c+ s}
+
+ def number: Parser[Int] =
+ for (val d <- digit; val ds <- rep(digit))
+ yield ((d - '0') foldl_: ds) {(x, y) => x * 10 + (y - '0')};
+
+ def expr: Parser[Tree] =
+ for {
+ val e1 <- expr1;
+ val es <- rep (
+ for {
+ val op <- chr('+') ||| chr('-');
+ val e <- expr1
+ } yield (x: Tree => Binop(op, x, e))
+ )
+ } yield (e1 foldl_: es) {(x,f) => f(x)}
+
+ def expr1: Parser[Tree] =
+ for {
+ val e1 <- expr2;
+ val es <- rep (
+ for {
+ val op <- chr('*') ||| chr('/');
+ val e <- expr2
+ } yield (x: Tree => Binop(op, x, e))
+ )
+ } yield (e1 foldl_: es) {(x,f) => f(x)}
+
+ def expr2: Parser[Tree] =
+ (for { val n <- ident } yield Var(n))
+ ||| (for { val n <- number } yield Num(n))
+ ||| (for { val _ <- chr('('); val e <- expr; val _ <- chr(')') } yield e);
+
+ private def applyAll[a](fs: List[a => a], x: a) =
+ (x foldl_: fs) { (x, f) => f(x) }
+}
diff --git a/sources/examples/patterns.scala b/sources/examples/patterns.scala
new file mode 100644
index 0000000000..3e4d5a5826
--- /dev/null
+++ b/sources/examples/patterns.scala
@@ -0,0 +1,28 @@
+module patterns {
+
+ trait Tree {}
+ case class Branch(left: Tree, right: Tree) extends Tree {}
+ case class Leaf(x: Int) extends Tree {}
+
+ val tree1 = Branch(Branch(Leaf(1), Leaf(2)), Branch(Leaf(3), Leaf(4)));
+
+ def sumLeaves(t: Tree): Int = t match {
+ case Branch(l, r) => sumLeaves(l) + sumLeaves(r)
+ case Leaf(x) => x
+ }
+
+ def find[a,b](it: Iterator[Pair[a, b]], x: a): Option[b] = {
+ var result: Option[b] = None();
+ while (it.hasNext && result.isNone) {
+ val Pair(x1, y) = it.next;
+ if (x == x1) result = Some(y)
+ }
+ result
+ }
+
+ def printFinds[a](xs: List[Pair[a, String]], x: a) =
+ find(xs.elements, x) match {
+ case Some(y) => System.out.println(y)
+ case None() => System.out.println("no match")
+ }
+} \ No newline at end of file
diff --git a/sources/examples/sort.scala b/sources/examples/sort.scala
new file mode 100644
index 0000000000..36d91b72ae
--- /dev/null
+++ b/sources/examples/sort.scala
@@ -0,0 +1,27 @@
+module sorter {
+
+def sort(a: Array[Int]): Unit = {
+
+ def swap(i: Int, j: Int): Unit = {
+ val t = a(i); a(i) = a(j); a(j) = t;
+ }
+
+ def sort1(l: Int, r: Int): Unit = {
+ val pivot = a((l + r) / 2);
+ var i = l, j = r;
+ while (i <= j) {
+ while (a(i) < pivot) { i = i + 1 }
+ while (a(j) > pivot) { j = j - 1 }
+ if (i <= j) {
+ swap(i, j);
+ i = i + 1;
+ j = j - 1;
+ }
+ }
+ if (l < j) sort1(l, j);
+ if (j < r) sort1(i, r);
+ }
+
+ sort1(0, a.length - 1);
+}
+} \ No newline at end of file
diff --git a/sources/examples/sort1.scala b/sources/examples/sort1.scala
new file mode 100644
index 0000000000..f2722b23cc
--- /dev/null
+++ b/sources/examples/sort1.scala
@@ -0,0 +1,12 @@
+import scala._;
+
+module sorter {
+
+ def sort(a: List[Int]): List[Int] = {
+ val pivot = a at (a.length / 2);
+ sort(a.filter(x => x < pivot))
+ ::: a.filter(x => x == pivot)
+ ::: sort(a.filter(x => x > pivot))
+ }
+
+} \ No newline at end of file
diff --git a/sources/examples/sort2.scala b/sources/examples/sort2.scala
new file mode 100644
index 0000000000..a4e32a9cd4
--- /dev/null
+++ b/sources/examples/sort2.scala
@@ -0,0 +1,12 @@
+module sorter {
+
+def sort (a: List[Int]): List[Int] = {
+ val pivot = a at (a.length / 2);
+ def leqPivot(x: Int) = x <= pivot;
+ def gtPivot(x: Int) = x > pivot;
+ def eqPivot(x: Int) = x == pivot;
+ sort(a filter leqPivot)
+ ::: sort(a filter eqPivot)
+ ::: sort(a filter gtPivot)
+}
+} \ No newline at end of file
diff --git a/sources/examples/typeinf.scala b/sources/examples/typeinf.scala
new file mode 100644
index 0000000000..5ff6f03f50
--- /dev/null
+++ b/sources/examples/typeinf.scala
@@ -0,0 +1,162 @@
+package examples;
+
+trait Term {}
+case class Var(x: String) extends Term {}
+case class Lam(x: String, e: Term) extends Term {}
+case class App(f: Term, e: Term) extends Term {}
+case class Let(x: String, e: Term, f: Term) extends Term {}
+
+module types {
+ trait Type {}
+ case class Tyvar(a: String) extends Type {}
+ case class Arrow(t1: Type, t2: Type) extends Type {}
+ case class Tycon(k: String, ts: List[Type]) extends Type {}
+ private var n: Int = 0;
+ def newTyvar: Type = { n = n + 1 ; Tyvar("a" + n) }
+}
+import types._;
+
+case class ListSet[a](elems: List[a]) {
+
+ def contains(y: a): Boolean = elems match {
+ case List() => False
+ case x :: xs => (x == y) || (xs contains y)
+ }
+
+ def union(ys: ListSet[a]): ListSet[a] = elems match {
+ case List() => ys
+ case x :: xs =>
+ if (ys contains x) ListSet(xs) union ys
+ else ListSet(x :: (ListSet(xs) union ys).elems)
+ }
+
+ def diff(ys: ListSet[a]): ListSet[a] = elems match {
+ case List() => ListSet(List())
+ case x :: xs =>
+ if (ys contains x) ListSet(xs) diff ys
+ else ListSet(x :: (ListSet(xs) diff ys).elems)
+ }
+}
+
+module typeInfer {
+
+ trait Subst extends Function1[Type,Type] {
+ def lookup(x: Tyvar): Type;
+ def apply(t: Type): Type = t match {
+ case Tyvar(a) => val u = lookup(Tyvar(a)); if (t == u) t else apply(u);
+ case Arrow(t1, t2) => Arrow(apply(t1), apply(t2))
+ case Tycon(k, ts) => Tycon(k, ts map apply)
+ }
+ def extend(x: Tyvar, t: Type) = new Subst {
+ def lookup(y: Tyvar): Type = if (x == y) t else Subst.this.lookup(y);
+ }
+ }
+
+ val emptySubst = new Subst { def lookup(t: Tyvar): Type = t }
+
+ def tyvars(t: Type): ListSet[String] = t match {
+ case Tyvar(a) => new ListSet(List(a))
+ case Arrow(t1, t2) => tyvars(t1) union tyvars(t2)
+ case Tycon(k, ts) => tyvars(ts)
+ }
+ def tyvars(ts: TypeScheme): ListSet[String] = ts match {
+ case TypeScheme(vs, t) => tyvars(t) diff new ListSet(vs)
+ }
+ def tyvars(ts: List[Type]): ListSet[String] = ts match {
+ case List() => new ListSet[String](List())
+ case t :: ts1 => tyvars(t) union tyvars(ts1)
+ }
+ def tyvars(env: Env): ListSet[String] = env match {
+ case List() => new ListSet[String](List())
+ case Pair(x, t) :: env1 => tyvars(t) union tyvars(env1)
+ }
+
+ case class TypeScheme(vs: List[String], t: Type) {
+ def newInstance: Type =
+ (emptySubst foldl_: vs) { (s, a) => s.extend(Tyvar(a), newTyvar) } (t);
+ }
+
+ type Env = List[Pair[String, TypeScheme]];
+
+ def lookup(env: Env, x: String): TypeScheme = env match {
+ case List() => null
+ case Pair(y, t) :: env1 => if (x == y) t else lookup(env1, x)
+ }
+
+ def gen(env: Env, t: Type): TypeScheme =
+ TypeScheme((tyvars(t) diff tyvars(env)).elems, t);
+
+ def mgu(t: Type, u: Type)(s: Subst): Subst = Pair(s(t), s(u)) match {
+ case Pair(Tyvar( a), Tyvar(b)) if (a == b) =>
+ s
+ case Pair(Tyvar(a), _) =>
+ if (tyvars(u) contains a) error("unification failure: occurs check")
+ else s.extend(Tyvar(a), u)
+ case Pair(_, Tyvar(a)) =>
+ mgu(u, t)(s)
+ case Pair(Arrow(t1, t2), Arrow(u1, u2)) =>
+ mgu(t1, u1)(mgu(t2, u2)(s))
+ case Pair(Tycon(k1, ts), Tycon(k2, us)) if (k1 == k2) =>
+ (s foldl_: ((ts zip us) map {case Pair(t,u) => mgu(t,u)})) { (s, f) => f(s) }
+ case _ => error("unification failure");
+ }
+
+ def tp(env: Env, e: Term, t: Type)(s: Subst): Subst = e match {
+ case Var(x) => {
+ val u = lookup(env, x);
+ if (u == null) error("undefined: x");
+ else mgu(u.newInstance, t)(s)
+ }
+ case Lam(x, e1) => {
+ val a = newTyvar, b = newTyvar;
+ val s1 = mgu(t, Arrow(a, b))(s);
+ val env1 = Pair(x, TypeScheme(List(), a)) :: env;
+ tp(env1, e1, b)(s1)
+ }
+ case App(e1, e2) => {
+ val a = newTyvar;
+ val s1 = tp(env, e1, Arrow(a, t))(s);
+ tp(env, e2, a)(s1)
+ }
+ case Let(x, e1, e2) => {
+ val a = newTyvar;
+ val s1 = tp(env, e1, a)(s);
+ tp(Pair(x, gen(env, s1(a))) :: env, e2, t)(s1)
+ }
+ }
+
+ def typeOf(env: Env, e: Term): Type = {
+ val a = newTyvar;
+ tp(env, e, a)(emptySubst)(a)
+ }
+}
+
+module predefined {
+ val booleanType = Tycon("Boolean", List());
+ val intType = Tycon("Int", List());
+ def listType(t: Type) = Tycon("List", List(t));
+
+ private def gen(t: Type): typeInfer.TypeScheme = typeInfer.gen(List(), t);
+ private val a = newTyvar;
+ val env = List(
+ Pair("true", gen(booleanType)),
+ Pair("false", gen(booleanType)),
+ Pair("if", gen(Arrow(booleanType, Arrow(a, Arrow(a, a))))),
+ Pair("zero", gen(intType)),
+ Pair("succ", gen(Arrow(intType, intType))),
+ Pair("nil", gen(listType(a))),
+ Pair("cons", gen(Arrow(a, Arrow(listType(a), listType(a))))),
+ Pair("isEmpty", gen(Arrow(listType(a), booleanType))),
+ Pair("head", gen(Arrow(listType(a), a))),
+ Pair("tail", gen(Arrow(listType(a), listType(a)))),
+ Pair("fix", gen(Arrow(Arrow(a, a), a)))
+ )
+}
+
+module test {
+
+ def showType(e: Term) = typeInfer.typeOf(predefined.env, e);
+
+ showType(Lam("x", App(App(Var("cons"), Var("x")), Var("nil"))));
+
+} \ No newline at end of file