計算理論において、ある計算のメカニズムが万能チューリングマシンと同じ計算能力をもつとき、その計算モデルはチューリング完全(チューリングかんぜん、Turing-complete)あるいは計算完備であるという。
- Combinatory Logic(コンビネータ論理)
- コンビネータ計算
- ラムダ計算
SKIコンビネータは,チューリング完全であることが証明されている。
S = x => y => z => x(z)(y(z));
K = x => y => x;
I = x => x;
B = f => g => x => f(g(x));
C = f => x => y => f(y)(x);
S(K)(K); // Iコンビネータ
S(K(S))(K); // 関数適用 Bコンビネータ
S(I)(I); // Loop
S(K(S(I)(I)))(S(S(K(S))K)(K(S(I)(I)))) // 再帰 Yコンビネータ
0 = K(I)
1 = I
2 = S(B)(I)
3 = S(B)(S(B)(I))
ラムダ計算は、計算模型のひとつで、計算の実行を関数への引数の評価(英語: evaluation)と適用(英語: application)としてモデル化・抽象化した計算体系である。
ラムダ計算は,チューリングマシンと等価な数理モデルである
TRUE := λx y. x // x => y => x;
FALSE := λx y. y // x => y => y;
NOT := λp. p FALSE TRUE // p => p(FALSE)(TRUE);
AND := λp q. p q FALSE
OR := λp q. p TRUE q
IF := λp x y. p x y
0 := λf x. x
1 := λf x. f x
2 := λf x. f (f x)
3 := λf x. f (f (f x))
SUCC := λn f x. f (n f x)
PLUS := λm n f x. m f (n f x)
MULT := λm n f. m (n f)
MULT := λm n. m (PLUS n) 0
PRED := λn f x. n (λg h. h (g f)) (λu. x) (λu. u)
const not = p => !p
const and = (p, q) => p && q
const or = (p, q) => p || q
const xor = (p, q) => !(p && q) && (p || q)
const eor = (p, q) => and(nand(p, q), or(p, q))
const comparator = fn => array => fn(...array)
const bit = [true, false];
const twobit = [
[false, false]
, [false, true]
, [true, false]
, [true, true]
];
console.log('not', bit.map(not));
console.log('and', twobit.map(comparator(and)));
console.log('or' , twobit.map(comparator(or)));
console.log('xor', twobit.map(comparator(xor)));
const p = console.log; // print
// TRUE/FALSE
const T = x => y => x; // λx y. x
const F = x => y => y; // λx y. y
// 確認
p(T); // p(T(true)(false));
p(F); // p(F(true)(false));
// NOT
const N = p => p(F)(T); // λp. p FALSE TRUE
// 確認
p(N(T)); // p(N(T)(true)(false));
p(N(F)); // p(N(F)(true)(false));
// IF
const IF = p => x => y => p(x)(y); // λp x y. p x y
p(IF(T));
p(IF(F));
// AND, OR, XOR (定義した T,F,N またはパラメータ p,q を用いて完成させよ)
const AND = p => q => ()()();
const OR = p => q => ()()();
const XOR = p => q => ()()();
const NAND = p => q => ()()();
const NOR = p => q => ()()();
const p = console.log;
// 準備運動
p('a', (x => x)(0));
p('b', (x => x)(x => x)(0));
p('c', (x => x)(x => x)(x => x)(0));
const I = x => x;
p('a', I(0));
p('b', I(I)(0));
p('c', I(I)(I)(0));
p('a', (x => x + 1)(0));
p('b', (x => x + 1)(x => x + 1)(0)); // error
p('c', (x => x + 1)(x => x + 1)(x => x + 1)(0)); // error
p('b#1', (x => x + 1)((x => x + 1)(0)));
p('b#2', (f => g => x => f(g(x)))(x => x + 1)(x => x +1)(0));
// 数値を関数で表す
// p((x => x)(0)); // 0
// p((x => x + 1)(0)); // 1
// p((x => x + 1)((x => x + 1)(0))); // 2
const identity = x => x;
const zero = 0;
const succ = x => x + 1;
// p(identity(zero)); // 0 f(x)
// p(succ(identity(zero))); // 1 f(f(x))
// p(succ(succ(identity(zero)))); // 2 f(f(f(x)))
const N = f => x => f(x); // n(f)(x);
// const ZERO = f => x => f(x); // f => x => x, x = 0
const ONE = f => x => f(x); // f => x => x + 1, x = 0
const TWO = f => x => f(f(x)); // f => x => x + 1, x = 0
const ZERO = f => x => x; // f => x => x + 1(fは,なんでもよい)
// N(f)(x)
p(ZERO(x = x + 1)(0));
p(ONE(x = x + 1)(0));
p(TWO(x = x + 1)(0));
const toInt = N => N(x => x + 1)(0);
p(toInt(ZERO));
p(toInt(ONE));
p(toInt(TWO));
//
const SUCC = n => f => x => f(n(f)(x));
const PLUS = m => n => f => x => (m)(f)(n(f)(x));
const MUL = m => n => f => m(n(f));
const POW = m => n => n(m);
const PRED = n => f => x => n(g => h => h(g(f)))(u => x)(u => u);