Skip to content

Instantly share code, notes, and snippets.

@zonuexe
Created March 6, 2019 10:12
Show Gist options
  • Save zonuexe/084264f6c042ca3bd89fe29852c096e7 to your computer and use it in GitHub Desktop.
Save zonuexe/084264f6c042ca3bd89fe29852c096e7 to your computer and use it in GitHub Desktop.
PHPでチャーチ数を使ってフィボナッチ数列
<?php declare(strict_types=1);
global $succ;
$succ = function ($n) {
return function ($f) use ($n) {
return function ($x) use ($n, $f) {
// ^n. ^f. ^x. f (n f x)
return $f($n($f)($x));
};
};
};
global $plus;
$plus = function ($n) {
return function ($m) use ($n) {
return function ($f) use ($n, $m) {
return function ($x) use ($n, $m, $f) {
// ^n. ^m. ^f. ^x. n f (m f x)
return $n($f)($m($f)($x));
};
};
};
};
$fib = function ($n): \Closure {
// ^n. n (^p. ^f. p (^a. ^b. f (plus a b) a))
return $n(
function ($p) {
return function ($f) use ($p) {
// p (^a. ^b. f (plus a b) a)
return $p(function ($a) use ($f) {
return function ($b) use ($f, $a) {
global $plus;
// f (plus a b) a
return $f($plus($a)($b))($a);
};
});
};
}
)
// (^f. f 1 0)
(function ($f) { return $f(n(1))(n(0)); })
// (^a. ^b. b)
(function ($a) {
return function ($b) use ($a) {
return $b;
};
});
};
assert(0 === toInt(n(0)));
assert(1 === toInt(n(1)));
assert(2 === toInt(n(2)));
assert(0 === toInt($plus(n(0))(n(0))));
assert(1 === toInt($plus(n(0))(n(1))));
assert(2 === toInt($plus(n(1))(n(1))));
assert( 1 === toInt($fib(n(1))));
assert( 1 === toInt($fib(n(2))));
assert( 2 === toInt($fib(n(3))));
assert( 3 === toInt($fib(n(4))));
assert( 5 === toInt($fib(n(5))));
assert( 8 === toInt($fib(n(6))));
assert(13 === toInt($fib(n(7))));
assert(21 === toInt($fib(n(8))));
echo "ok", PHP_EOL;
exit;
function toInt(\Closure $f)
{
//var_dump($f);
return $f(function ($n) { return $n + 1; })(0);
}
function n(int $n)
{
global $succ;
static $num = [];
if (empty($num)) {
$num[0] = function ($s) { return function ($z) use ($s) { return $z; }; };
$num[1] = function ($s) { return function ($z) use ($s) { return $s($z); }; };
}
if (!isset($num[$n])) {
$num[$n] = $succ(n($n - 1));
}
return $num[$n];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment