人気ブログランキング | 話題のタグを見る

三段論法

「ソクラテスは人間だ、人間は死ぬ、故にソクラテスは死ぬ」という三段論法を Haskell でやってみよう。

先ず、「ソクラテスは人間だ」、「人間は死ぬ」などの含意をペアで表現し、その集合 implications を次のように作る。

Prelude> let implications = [("Socrates", "human"), ("human", "mortal")]

lookup 関数で前件から後件を検索する。前件を含む含意があれば、後件を次のように取り出すことができる。

Prelude> lookup "Socrates" implications
Just "human"

三段論法はこのような検索を「ソクラテス」->「人間」->「死ぬ」とつなげていくだけだ。プログラムが少し長くなるのでファイルを作成した。

ファイル名: test.hs

implications = [("Socrates", "human"), ("human", "mortal")]

helper antecedent Nothing = antecedent
helper antecedent (Just consequent) =
  helper consequent (lookup consequent implications)

deduct antecedent = helper antecedent (lookup antecedent implications)

implication はペアで表現された含意のリストだ。helper 関数は前件と前件から検索された後件という2つの引き数をとり。後件が Nothing つまり後件の検索に失敗したときは前件を返す。また、後件が見つかったときはそれを新しい前件として、検索を続ける。

前件から三段論法する deduct 関数は、helper 関数を用いて定義する。前件 antecedent を引数に取り、これと (lookup antecedent implications) の2つを引き数にとる helper 関数で定義する。

実行例は次のようになる。

*Main Prelude> deduct "Socrates"
"mortal"

これでは、推論の途中経過がわからないので、途中経過を表示するようにプログラムを変更した。途中経過の表示は IO モナドのなかで行わなければならないので面倒になるのではないかと思ったがあっさりできてしまった。

ファイル名: test2.hs

implications = [("Socrates", "human"), ("human", "mortal")]

helper antecedent Nothing = print antecedent
helper antecedent (Just consequent) = do
  print (antecedent ++ " -> " ++ consequent)
  helper consequent (lookup consequent implications)

deduct antecedent = helper antecedent (lookup antecedent implications)

実行例は次のようになる。

*Main Prelude> deduct "Socrates"
"Socrates -> human"
"human -> mortal"
"mortal"
by tnomura9 | 2012-06-18 13:20 | Haskell | Comments(0)
<< Haskell の print... RWH の読み方(51) 第7章 >>