Skip to content

Instantly share code, notes, and snippets.

@osa9
Created August 27, 2011 02:39
Show Gist options
  • Save osa9/1174882 to your computer and use it in GitHub Desktop.
Save osa9/1174882 to your computer and use it in GitHub Desktop.
オブジェクト指向で遊んでみる
//---------------------------------------
// オブジェクト指向で遊んでみる
//---------------------------------------
//---------------------------------------
// 補助クラス
//---------------------------------------
// 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));
}
}
@osa9
Copy link
Author

osa9 commented Aug 27, 2011

実行結果:
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment