Created
April 15, 2010 16:08
-
-
Save tarao/367299 to your computer and use it in GitHub Desktop.
Enumerating prime numbers in Featherweight Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////// | |
// Lazy evaluation | |
class Obj extends Object { | |
Obj(){ super(); } Obj eval(){ return this; } | |
} | |
//////////////////////////////////////////////// | |
// Error indicator | |
class Error extends Obj { Error(){ super(); } } | |
//////////////////////////////////////////////// | |
// Boolean | |
class Bool extends Obj { | |
Bool(){ super(); } | |
Bool neg(){ return new False(); } | |
Bool or(Obj b){ return this; } | |
Bool and(Obj b){ return (Bool)b.eval(); } | |
Obj cond(Obj thn, Obj els){ return thn.eval(); } | |
} | |
class True extends Bool { True(){ super(); } } | |
class False extends Bool { | |
False(){ super(); } | |
Bool neg(){ return new True(); } | |
Bool or(Obj b){ return (Bool)b.eval(); } | |
Bool and(Obj b){ return this; } | |
Obj cond(Obj thn, Obj els){ return els.eval(); } | |
} | |
//////////////////////////////////////////////// | |
// Natural number | |
class N extends Obj { | |
N(){ super(); } | |
N pre(){ return (N)(Obj)new Error(); } | |
N suc(){ return new S(this); } | |
N add(N m){ return m; } | |
N sub(N m){ return (N)m.isZero().cond(this, new Error()); } | |
N mul(N m){ return this; } | |
N div(N m){ return (N)this.divRem(m).car(); } | |
N mod(N m){ return (N)this.divRem(m).cdr().car(); } | |
List divRem(N m) { | |
return (List)m.isZero().cond(new List().one(new Error()), | |
new List().two(new Z(), new Z())); | |
} | |
Bool isZero(){ return new True(); } | |
Bool isSucOf(N m){ return new False(); } | |
Bool eq(N m){ return m.isZero(); } | |
Bool ne(N m){ return this.eq(m).neg(); } | |
Bool gt(N m){ return new False(); } | |
Bool lt(N m){ return m.gt(this); } | |
Bool ge(N m){ return this.eq(m).or(this.gt(m)); } | |
Bool le(N m){ return m.ge(this); } | |
} | |
class Z extends N { Z(){ super(); } } | |
class S extends Z { | |
N n; S(N n){ super(); this.n=n; } | |
N pre(){ return this.n; } | |
N add(N m){ return this.n.add(m).suc(); } | |
N sub(N m) { return (N)m.isZero().cond(this, new SubElse(this.n, m)); } | |
N mul(N m){ return (N)m.add(this.n.mul(m)); } | |
List divRem(N m) { | |
return (List)m.isZero().cond(new List().one(new Error()), | |
new DivRemElse1(this, m)); | |
} | |
Bool isZero(){ return new False(); } | |
Bool isSucOf(N m){ return m.eq(this.n); } | |
Bool eq(N m){ return m.isSucOf(this.n); } | |
Bool gt(N m){ return this.n.ge(m); } | |
} | |
class SubElse extends Obj { | |
N n; N m; SubElse(N n, N m){ super(); this.n=n; this.m=m; } | |
Obj eval(){ return this.n.sub(this.m.pre()); } | |
} | |
class DivRemElse1 extends Obj { | |
N n; N m; DivRemElse1(N n, N m){ super(); this.n=n; this.m=m; } | |
Obj eval() { | |
return this.n.lt(this.m).cond(new List().two(new Z(), this.n), | |
new DivRemElse2(this.n, this.m)); | |
} | |
} | |
class DivRemElse2 extends DivRemElse1 { | |
DivRemElse2(N n, N m){ super(n, m); } | |
List sucCar(List l){ return new Cons(((N)l.car()).suc(), l.cdr()); } | |
Obj eval() { return this.sucCar(this.n.sub(this.m).divRem(this.m)); } | |
} | |
//////////////////////////////////////////////// | |
// List | |
class List extends Obj { | |
List(){ super(); } | |
Bool isNil(){ return new True(); } | |
Obj car(){ return this; } | |
List cdr(){ return new List(); } | |
List one(Obj a){ return new Cons(a, new Nil()); } | |
List two(Obj a, Obj b){ return new Cons(a, new List().one(b)); } | |
} | |
class Nil extends List { Nil(){ super(); } } | |
class Cons extends List { | |
Obj car; List cdr; | |
Cons(Obj car, List cdr){ super(); this.car=car; this.cdr=cdr; } | |
Obj car(){ return this.car; } | |
Bool isNil(){ return new False(); } | |
List cdr(){ return this.cdr; } | |
} | |
//////////////////////////////////////////////// | |
// Infinite sequence | |
class Seq extends Obj { | |
Obj val; Next next; | |
Seq(Obj val, Next next){ super(); this.val=val; this.next=next; } | |
Obj car(){ return this.val; } | |
Seq cdr(){ return this.next.get(); } | |
List take(N n) { | |
return (List)n.isZero().cond(new Nil(), new Take(n, this)); | |
} | |
} | |
class Next extends Obj { | |
Next(){ super(); } Seq get(){ return new Seq(new Obj(), this); } | |
} | |
class Take extends Obj { | |
N n; Seq s; Take(N n, Seq s){ super(); this.n=n; this.s=s; } | |
Obj eval() { | |
return new Cons(this.s.car(), this.s.cdr().take(this.n.pre())); | |
} | |
} | |
//////////////////////////////////////////////// | |
// Generating prime numbers | |
class Sift extends Next { | |
N n; Seq s; Sift(N n, Seq s){ super(); this.n=n; this.s=s; } | |
Seq get() { | |
return (Seq)((N)this.s.car()).mod(this.n).isZero() | |
.cond(new SiftThen(this), new SiftElse(this)); | |
} | |
} | |
class SiftThen extends Obj { | |
Sift si; SiftThen(Sift si){ super(); this.si=si; } | |
Obj eval(){ return new Sift(this.si.n, this.si.s.cdr()).get(); } | |
} | |
class SiftElse extends Obj { | |
Sift si; SiftElse(Sift si){ super(); this.si=si; } | |
Obj eval(){ return new Seq(this.si.s.car(), new SiftElseNext(this)); } | |
} | |
class SiftElseNext extends Next { | |
SiftElse se; SiftElseNext(SiftElse se){ super(); this.se=se; } | |
Seq get(){ return new Sift(this.se.si.n, this.se.si.s.cdr()).get(); } | |
} | |
class Sieve extends Next { | |
Seq s; Sieve(Seq s){ super(); this.s=s; } | |
Seq get(){ return new Seq(this.s.car(), new SieveNext(this)); } | |
} | |
class SieveNext extends Next { | |
Sieve si; SieveNext(Sieve si){ super(); this.si=si; } | |
Seq get() { | |
return new Sieve(new Sift((N)this.si.s.car(), | |
this.si.s.cdr()).get()).get(); | |
} | |
} | |
class PrimeSeq extends Next { | |
PrimeSeq(){ super(); } | |
N n2(){ return new Z().suc().suc(); } N n3(){ return this.n2().suc(); } | |
Seq get() { | |
return new Sieve(new Seq(this.n2(), new From2(this.n3()))).get(); | |
} | |
} | |
class From2 extends Next { | |
N n; From2(N n){ super(); this.n=n; } | |
Seq get(){ return new Seq(this.n, new From2(this.n.suc().suc())); } | |
} | |
//////////////////////////////////////////////// | |
// Test | |
class Test { | |
static class PP { | |
static Integer toInteger(N n) { | |
int i=0; | |
for (; n instanceof S; i++) n = ((S)n).n; | |
return new Integer(i); | |
} | |
static String toString(Object obj) { | |
if (obj instanceof True) { | |
return "true"; | |
} else if (obj instanceof False) { | |
return "false"; | |
} else if (obj instanceof N) { | |
return ""+toInteger((N)obj); | |
} else if (obj instanceof List) { | |
List ls = (List)obj; | |
if (!(ls instanceof Cons)) return "[]"; | |
String s = toString(ls.car()); | |
for (ls = ls.cdr(); ls instanceof Cons; ls = ls.cdr()) { | |
s += "," + toString(ls.car()); | |
} | |
return "[" + s + "]"; | |
} | |
return "unknown: " + obj.getClass().getName(); | |
} | |
} | |
public static void main(String[] args) { | |
N two = new Z().suc().suc(); | |
N eight = two.mul(two).mul(two); | |
List ls = new PrimeSeq().get().take(eight.mul(eight)); | |
System.out.println(PP.toString(ls)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment