人気ブログランキング |

Text.Parsec.Prim: 抽象的プログラム

ParsecT s u m a パーサのフィールドのデータは次のように状態 s と継続 cok cerr eok eerr を引数とする無名関数だ。

\s cok eerr eok eerr -> some function

実のところ、この関数はパターンマッチのテストとその結果の要素的データを返すことしかしていない。それ以後の処理は皆 cok cerr eok eerr のどれかの継続に委嘱してしまう。したがって、実体的な処理は外部からコントロールすることになる。この関数はパターンマッチを行ってその結果を返すという抽象的な処理しかやっていない。

このような抽象的なプログラムは、プログラムの書き直しをせずに色々な用途に利用できるという特徴がある。そこで、簡単な抽象的プログラムを作って実験してみた。次のプログラム foo は値 x と関数 test ok error を引数とする高階関数だ。値 x に関する test を行い test x が真なら ok x を実行し、偽なら err x を実行する。foo はテストと分岐だけを行う抽象的動作しかしない。

Prelude> foo x test ok err = if test x then ok x else err x

foo に何か実体的な動作を行わせるためには、ユーザが foo と ok と err に適当な関数を与える必要がある。

Prelude> foo 3 odd (\x -> "odd") (\x -> "even")
"odd"

戻り値を Maybe 型にすることも可能だ。foo には全く手を入れていない。

Prelude> foo 3 odd (\x -> Just x) (\x -> Nothing)
Just 3

パターンマッチも同じ foo 関数でできる。

Prelude> foo "bar" (=="bar") (\x -> Just x) (\x -> Nothing)
Just "bar"

foo を使った再帰関数も定義できる。

Prelude> fact n = foo n (==0) (\x -> 1) (\x -> x * fact (x-1))
Prelude> fact 5
120

foo 関数には何かをテストしてその値に応じて分岐するという抽象的な機能しかないので、逆に、そのパターンにマッチする多種多様なプログラムを記述できる。foo のような抽象関数が記述できるのは、Haskell では引数として関数を与えることができるからだ。


by tnomura9 | 2019-08-13 23:34 | Haskell | Comments(0)
<< Text.Parsec.Pri... Text.Parsec.Pri... >>