diff options
author | Martin Odersky <odersky@gmail.com> | 2003-03-03 14:33:53 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2003-03-03 14:33:53 +0000 |
commit | 6749e5dd658522cb63600021a9ee5a86f911cfeb (patch) | |
tree | a22d4bf7f2bf71b5775418dfddaa31a1640313d1 /sources/examples | |
parent | e1fb3fb655a067039870016b3a47e2305d692d98 (diff) | |
download | scala-6749e5dd658522cb63600021a9ee5a86f911cfeb.tar.gz scala-6749e5dd658522cb63600021a9ee5a86f911cfeb.tar.bz2 scala-6749e5dd658522cb63600021a9ee5a86f911cfeb.zip |
*** empty log message ***
Diffstat (limited to 'sources/examples')
-rw-r--r-- | sources/examples/fors.scala | 63 | ||||
-rw-r--r-- | sources/examples/iterators.scala | 12 | ||||
-rw-r--r-- | sources/examples/maps.scala | 152 | ||||
-rw-r--r-- | sources/examples/parsers.scala | 53 | ||||
-rw-r--r-- | sources/examples/parsers1.scala | 115 | ||||
-rw-r--r-- | sources/examples/patterns.scala | 28 | ||||
-rw-r--r-- | sources/examples/sort.scala | 27 | ||||
-rw-r--r-- | sources/examples/sort1.scala | 12 | ||||
-rw-r--r-- | sources/examples/sort2.scala | 12 | ||||
-rw-r--r-- | sources/examples/typeinf.scala | 162 |
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 |