Created
August 27, 2011 02:39
-
-
Save osa9/1174882 to your computer and use it in GitHub Desktop.
オブジェクト指向で遊んでみる
This file contains 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
//--------------------------------------- | |
// オブジェクト指向で遊んでみる | |
//--------------------------------------- | |
//--------------------------------------- | |
// 補助クラス | |
//--------------------------------------- | |
// Void型 | |
class Void {} | |
// 関数をカプセルするクラス | |
abstract class Functor<T,U> { | |
public abstract U apply(T t); | |
} | |
//--------------------------------------- | |
// 真偽型の定義 | |
//--------------------------------------- | |
abstract class Boolean { | |
public abstract <T> T get(T t,T f); | |
} | |
class True extends Boolean { | |
@Override | |
public <T> T get(T t, T f) { return t; } | |
} | |
class False extends Boolean { | |
@Override | |
public <T> T get(T t, T f) { return f; } | |
} | |
//--------------------------------------- | |
// 論理演算の定義 | |
//--------------------------------------- | |
class Bool { | |
public Boolean not(Boolean b) { | |
return b.get(new False(), new True()); | |
} | |
public Boolean and(Boolean a, Boolean b) { | |
return a.get(b.get(new True(), new False()), new False()); | |
} | |
public Boolean or(Boolean a, Boolean b) { | |
return a.get(new True(), b.get(new True(), new False())); | |
} | |
} | |
//--------------------------------------- | |
// 条件分岐の定義 | |
//--------------------------------------- | |
class Condition { | |
public <T> T iif(Boolean b, T t, T f) { | |
return b.get(t,f); | |
} | |
// 遅延評価版if | |
public <T> T lazyIf(Boolean b, Functor<Void,T> t, Functor<Void,T> f) { | |
return iif(b,t,f).apply(new Void()); | |
} | |
} | |
//--------------------------------------- | |
// 自然数の定義 | |
//--------------------------------------- | |
abstract class Number { | |
public abstract Number add(Number n); | |
public abstract <T> T apply(Functor<T,T> op, T t); | |
} | |
// 0は自然数 | |
class Zero extends Number { | |
@Override | |
public Number add(Number n) { return n; } | |
@Override | |
public <T> T apply(Functor<T,T> op, T t) { return t; } | |
} | |
// nが自然数ならn+1も自然数 | |
class Succ extends Number { | |
final Number n; | |
public Succ(Number n) { this.n = n; } | |
@Override | |
public Number add(Number m) { | |
return new Succ(m.add(n)); | |
} | |
@Override | |
public <T> T apply(Functor<T,T> op, T t) { | |
return n.apply(op, op.apply(t)); | |
} | |
} | |
//--------------------------------------- | |
// 自然数演算のための補助クラス | |
//--------------------------------------- | |
// ペア | |
class Pair<T,U> { | |
public final T fst; | |
public final U snd; | |
public Pair(T fst, U snd) { | |
this.fst = fst; | |
this.snd = snd; | |
} | |
} | |
// T -> U | |
class Const<T,U> extends Functor<T,U> { | |
final U u; | |
public Const(U u) { | |
this.u = u; | |
} | |
@Override | |
public U apply(T t) { | |
return u; | |
} | |
} | |
// Void -> U | |
class Const0<U> extends Const<Void,U> { | |
public Const0(U u) { | |
super(u); | |
} | |
} | |
//--------------------------------------- | |
// 自然数演算クラス | |
//--------------------------------------- | |
class Num { | |
// 0かどうか | |
public Boolean isZero(Number n) { | |
return n.apply(new Const<Boolean,Boolean>(new False()),new True()); | |
} | |
// 自然数の足し算 | |
public Number add(Number lhs, Number rhs) { | |
return lhs.apply(new Functor<Number,Number>() { | |
@Override | |
public Number apply(Number n) { | |
return new Succ(n); | |
}}, rhs); | |
} | |
// 自然数のかけ算 | |
public Number mul(Number lhs, final Number rhs) { | |
return lhs.apply(new Functor<Number,Number>() { | |
@Override | |
public Number apply(Number n) { | |
return add(n,rhs); | |
}}, new Zero()); | |
} | |
// -1 | |
public Number pred(Number n) { | |
return n.apply(new Functor<Pair<Number,Number>,Pair<Number,Number>>() { | |
@Override | |
public Pair<Number,Number> apply(Pair<Number,Number> pair) { | |
return new Pair<Number,Number>(pair.snd, new Succ(pair.snd)); | |
} | |
}, new Pair<Number,Number>(new Zero(),new Zero())).fst; | |
} | |
// 自然数の引き算 | |
public Number sub(Number lhs, Number rhs) { | |
return rhs.apply(new Functor<Number,Number>() { | |
@Override | |
public Number apply(Number n) { | |
return pred(n); | |
}}, lhs); | |
} | |
} | |
//--------------------------------------- | |
// 自然数比較の補助クラス | |
//--------------------------------------- | |
// 手続きを遅延するクラス | |
abstract class Lazy<U> extends Functor<Void,U> { | |
public abstract U get(); | |
@Override | |
public U apply(Void _v) { | |
return get(); | |
} | |
} | |
// -1するクラス | |
class Pred extends Functor<Number,Number> { | |
@Override | |
public Number apply(Number n) { | |
return new Num().pred(n); | |
} | |
} | |
// eqの再帰を遅延 | |
class LazyEqPred extends Lazy<Boolean> { | |
final Number lhs; | |
final Number rhs; | |
public LazyEqPred(Number lhs, Number rhs) { | |
this.lhs = lhs; | |
this.rhs = rhs; | |
} | |
@Override | |
public Boolean get() { | |
return new Comp().eq(new Num().pred(lhs), new Num().pred(rhs)); | |
} | |
} | |
//--------------------------------------- | |
// 自然数比較演算クラス | |
//--------------------------------------- | |
class Comp { | |
// less than | |
public Boolean lt(Number m, Number n) { | |
return new Bool().not(new Num().isZero(new Num().sub(n,m))); | |
} | |
// greater than | |
public Boolean gt(Number m, Number n) { | |
return lt(n,m); | |
} | |
// 無限に再帰してしまうeqの定義 | |
/* | |
public Boolean eq(Number lhs, Number rhs) { | |
return new Condition().iif( | |
new Bool().and(new Num().isZero(lhs), new Num().isZero(rhs)), | |
new True(), | |
new Condition().iif( | |
new Bool().or(new Num().isZero(lhs), new Num().isZero(rhs)), | |
new False(), | |
eq(new Num().pred(lhs), new Num().pred(rhs)))); | |
} */ | |
// equal | |
public Boolean eq(Number lhs, Number rhs) { | |
return new Condition().iif( | |
new Bool().and(new Num().isZero(lhs),new Num().isZero(rhs)), | |
new True(), | |
new Condition().lazyIf( | |
new Bool().or(new Num().isZero(lhs),new Num().isZero(rhs)), | |
new Const0<Boolean>(new False()), | |
new LazyEqPred(lhs,rhs))); | |
} | |
} | |
//--------------------------------------- | |
// フィボナッチ関数 | |
//--------------------------------------- | |
// フィボナッチの遅延再帰クラス | |
class FibRec extends Lazy<Number> { | |
final Number n; | |
public FibRec(Number n) { | |
this.n = n; | |
} | |
public Number get() { | |
return new Num().add( | |
new Fib().fib(new Num().pred(n)), | |
new Fib().fib(new Num().pred(new Num().pred(n))) | |
); | |
} | |
} | |
// フィボナッチクラス | |
class Fib { | |
public Number fib(Number n) { | |
return new Condition().iif( | |
new Num().isZero(n), | |
new Zero(), | |
new Condition().lazyIf( | |
new Comp().lt(n, new Succ(new Succ(new Zero()))), | |
new Const0<Number>(new Succ(new Zero())), | |
new FibRec(n))); | |
} | |
} | |
//--------------------------------------- | |
// Main | |
//--------------------------------------- | |
public class Main { | |
public static void main(String[] args) { | |
// 色々テストしてみる | |
System.out.print("if true then 1 else 0 ==> "); | |
print(new Condition().iif(new True(), new Succ(new Zero()), new Zero())); | |
System.out.print("if false then false else true ==> "); | |
print(new Condition().iif(new False(), new False(), new True())); | |
System.out.print("not true ==> "); | |
print(new Bool().not(new True())); | |
System.out.print("not false ==> "); | |
print(new Bool().not(new False())); | |
System.out.print("true and true ==> "); | |
print(new Bool().and(new True(), new True())); | |
System.out.print("true and false ==> "); | |
print(new Bool().and(new True(), new False())); | |
System.out.print("succ(succ(zero)) ==> "); | |
print(new Succ(new Succ(new Zero()))); | |
System.out.print("zero is zero ==> "); | |
print(new Num().isZero(new Zero())); | |
System.out.print("succ(zero) is zero ==> "); | |
print(new Num().isZero(new Succ(new Zero()))); | |
System.out.print("2 + 3 ==> "); | |
print(new Num().add(new Succ(new Succ(new Zero())), | |
new Succ(new Succ(new Succ(new Zero()))))); | |
System.out.print("3 * 5 ==> "); | |
print(new Num().mul(toNum(3),toNum(5))); | |
System.out.print("75 - 50 ==> "); | |
print(new Num().sub(toNum(75),toNum(50))); | |
System.out.print("3 < 5 ==> "); | |
print(new Comp().lt(toNum(3),toNum(5))); | |
System.out.print("3 < 3 ==> "); | |
print(new Comp().lt(toNum(3),toNum(3))); | |
System.out.print("5 < 3 ==> "); | |
print(new Comp().lt(toNum(5),toNum(3))); | |
System.out.print("50 = 50 ==> "); | |
print(new Comp().eq(toNum(50),toNum(50))); | |
System.out.print("50 = 51 ==> "); | |
print(new Comp().eq(toNum(50),toNum(51))); | |
System.out.println("fib(0..5) ==> "); | |
print(new Fib().fib(toNum(0))); | |
print(new Fib().fib(toNum(1))); | |
print(new Fib().fib(toNum(2))); | |
print(new Fib().fib(toNum(3))); | |
print(new Fib().fib(toNum(4))); | |
print(new Fib().fib(toNum(5))); | |
} | |
/* intからNumberを生成する補助関数 */ | |
private static Number toNum(int n) { | |
if(n <= 0) return new Zero(); | |
else return new Succ(toNum(n-1)); | |
} | |
/* BooleanのPretty Print */ | |
private static void print(Boolean b) { | |
System.out.println(new Condition().iif(b, "True", "False")); | |
} | |
/* NumberのPretty Print */ | |
private static void print(Number n) { | |
System.out.println( | |
n.apply(new Functor<Integer,Integer>() { | |
@Override | |
public Integer apply(Integer n) { | |
return n + 1; | |
} | |
}, 0)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
実行結果:
if true then 1 else 0 ==> 1
if false then false else true ==> True
not true ==> False
not false ==> True
true and true ==> True
true and false ==> False
succ(succ(zero)) ==> 2
zero is zero ==> True
succ(zero) is zero ==> False
2 + 3 ==> 5
3 * 5 ==> 15
75 - 50 ==> 25
3 < 5 ==> True
3 < 3 ==> False
5 < 3 ==> False
50 = 50 ==> True
50 = 51 ==> False
fib(0..5) ==>
0
1
1
2
3
5