Mercury 勉強メモ

関数論理型言語 Mercury を勉強するブログです.

Mercury 入門 (2) 式の計算と独自の述語の定義

今回は Mercury で数式計算をする方法を学びます. 以下は,12 + 13を計算して画面に25と表示するMercuryのプログラムです.

実行結果

$ mmc arith.m
$ ./arith
12 + 13 = 25

数値演算を行うためには,最初にintモジュールが必要なので, 実装部の最初でインポートしています.

=/2は単一化を行う組み込みの述語で,

項1 = 項2

のように使って,項1と項2を等しくできる代入を見つけることが出来れば, その代入処理を行なって成功し,等しくできない場合は失敗します. 上の例では=/2を3回使っています. =の左辺と右辺に区別はなく,例えば,

X + Y = Z

と,

Z = X + Y

はどちらも同じ効果になります.

上のプログラムでは,ioモジュールの,標準出力に整数を表示する述語write_intと, 改行文字を出力する述語nlが使われています.それぞれの宣言を以下に示します.

:- pred io.write_int(int::in, io::di, io::uo) is det.
:- pred io.nl(io::di, io::uo) is det.

整数に関する関数

+のように式の中で使えて,値を返す述語をMercuryでは関数とよびます. Mercuryの整数に関する代表的な関数には以下のものがあります.

  • - 式: 符号反転
  • 式1 + 式2: 加算
  • 式1 - 式2: 減算
  • 式1 * 式2: 乗算
  • div(式1, 式2): 除算
  • mod(式1, 式2): 剰余

整数に関する述語

成功か失敗を返すのが述語です.整数に関するものとしては以下のものがあります.

  • 式1 < 式2: より小さい
  • 式1 > 式2: より大きい
  • 式1 =< 式2: 以下 (注: 一般的な言語と表記が異なっています)
  • 式1 >= 式2: 以上
  • 式1 \= 式2: 等しくない

独自の述語を作る

Mercury では宣言と実装を書くことで,独自の述語を自由に追加できます. 例えば,Xを入力として受け取ってX * 2を出力として返す述語は,

:- pred double(int::in, int::out) is det.
double(X, Y) :- X * 2 = Y.

のように書けます.

この述語を含むプログラム全体を以下に示します.

実行結果

20

以下のプログラムのaddmul/4のように,複数の入力を受け取って,複数の出力を返す述語も 記述できます.

実行結果

Add = 5
Mul = 6

if then else ゴール

述語が成功したか失敗したかによって分岐させたい場合は, if then else ゴールを使います. if then else ゴールは,

if   G1, G2, ..., Gn
then H1, H2, ..., Hn
else I1, I2, ..., In

のような形式で,G1, G2, ..., Gnのすべてが成功したときは, H1, H2, ..., Hnの真偽を返し, G1, G2, ..., Gnのいずれかが失敗したときは, I1, I2, ..., Inの真偽を返します.

再帰的な述語の定義

述語の定義の中で,今定義しつつある述語を利用することができます. このような自分自身をよぶ述語を再帰的な述語であるといいます. 以下の例では,述語を再帰的によぶことで階乗計算をしています.

実行結果

fact(5) = 120