このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

述語論理はJavaScriptを使うべきだった

あー、失敗。「プログラマのための述語論理」は、説明にJavaScriptを使うべきだった(「みにくいアヒルの子 -- コンピューティング・サイエンスとJavaScript」も参照)。技巧的なJavaコードじゃ、分かるものも分からなくなる。

手遅れだろうけど、JavaScriptで書き直し。

述語の例

function positive(n) {
 return n > 0;
}
function zero(n) {
 return n === 0;
}
function empty(s) {
 return s === "";
}

述語論理の演算

function and(p, q) {
 return function(x) {
   return p.call(null, x) && q.call(null, x);
 };
}
function or(p, q) {
 return function(x) {
   return p.call(null, x) || q.call(null, x);
 };
}
function not(p) {
 return function(x) {
   return ! p.call(null, x);
 };
}

述語の演算デモ

var positiveOrZero = or(positive, zero);
var notEmpty = not(empty);
var intData = [1, 0, -2, 3, -1];
var strData = ["Hello", "", "World"];

for(var i in intData) {
 var n = intData[i];
 print("positiveOrZero " + n + " = " + positiveOrZero(n));
}
for(var i in strData) {
 var s = strData[i];
 print("notEmpty " + s + " = " + notEmpty(s));
}


positiveOrZero 1 = true
positiveOrZero 0 = true
positiveOrZero -2 = false
positiveOrZero 3 = true
positiveOrZero -1 = false
notEmpty Hello = true
notEmpty = false
notEmpty World = true

限量子の実現

function forAll(domain, pred) {
 for(var i in domain) {
  var x = domain[i];
  if (! pred.call(null, x)) {
   return false;
  }
 }
 return true;
}
function forSome(domain, pred) {
 for(var i in domain) {
  var x = domain[i];
  if (pred.call(null, x)) {
   return true;
  }
 }
 return false;
}

限量子のデモ

var formula;
var truth;

formula ="ForAll s in {\"Hello\", \"\", \"World\"}.(Not empty(s))";
truth = forAll(["Hello", "", "World"], notEmpty);
print(formula + " ==> " + truth);

formula = "ForAll s in {\"Hello\", \"Hello\", \"World\"}.(Not empty(s))";
truth = forAll(["Hello", "Hello", "World"], notEmpty);
print(formula + " ==> " + truth);

formula = "ForSome x in {-1, -2, 0, 3}.(positive(x) Or zero(x))";
truth = forSome([-1, -2, 0, 3], positiveOrZero);
print(formula + " ==> " + truth);

formula = "ForSome x in {-1, -2, -3}.(positive(x) Or zero(x))";
truth = forSome([-1, -2, -3], positiveOrZero);
print(formula + " ==> " + truth);


ForAll s in {"Hello", "", "World"}.(Not empty(s)) ==> false
ForAll s in {"Hello", "Hello", "World"}.(Not empty(s)) ==> true
ForSome x in {-1, -2, 0, 3}.(positive(x) Or zero(x)) ==> true
ForSome x in {-1, -2, -3}.(positive(x) Or zero(x)) ==> false

それで、さらに

あー、やっぱり、JavaScriptのほうがはるかに簡単で素直。“述語”の型を“X→Boolean”のように特定(強く型付け)できない点がJavaScriptの問題といえば問題。JavaScript2.0には、高階型や型総称は入る予定ないよなぁ(見た記憶がない)、もし次のように書けたらサイコーなんだけど。

function<X> forAll(domain:Collection<X>, pred:X->Boolean):Boolean {
 for(var i in domain) {
  var x:X = domain[i];
  if (! pred.call(null, x)) {
   return false;
  }
 }
 return true;
}