🥁

参照透過性について(Haskell)

2022/07/08に公開

この記事では参照透過性についてカンタンにまとめます。参照透過性とは同じ引数で呼び出した関数は常に同じ結果を返却する..という性質のことです。 「同じ引数ならいつでも同じ戻り値になる」という性質を持つ関数であり、数学らしい特徴とも言えます。(数学における関数は呼び出した状況で値が変わるというようなことはないはずです。)Haskellではこの数学的な性質を利用してプログラムを組み立てることになります。

参照透過性のある関数

数学的な関数とは何でしょうか。例えば投入された数値を2倍にするnibai関数です。nibai関数に2という数値を渡すと4という数値が返却されます。

nibai :: Int -> Int
nibai num = num * 2
main = print $ nibai 2
実行結果
4

同じ引数ならいつでも同じ結果を得ることができます。これは数学的な関数であり、参照透過性を持つ関数であると言えます。

参照透過性のない関数

逆に参照透過性のない関数とは何でしょうか。例えばグローバル変数に対して数値を+1する関数はどうでしょうか。countup関数としてC言語で書いてみます。

#include <stdio.h>
int num;

int countup(void){
    num++;
    printf("%d\n", num);
    return num;
}

int main(void){
    countup();
    countup();
    countup();
    return 0;
}
実行結果
1
2
3

同じcountup関数を呼び出すにも関わらず、1回目,2回目,3回目で結果が変わっています。引数の値だけでは処理結果が決まらない、参照透過性のない関数です。このような関数は数学的とは呼べません。一般に関数型プログラミングと呼ぶときは、数学的な関数の特徴を持つプログラミング言語のことを指します。 「いつ呼び出しても同じ結果」というルールを設けることで安全なプログラムを作れるメリットがあります。

束縛と何が違う?

ちなみに参照透過性と似た概念として「束縛」というモノがあります。参照透過性は関数にまつわる概念ですが、束縛とは変数に関係するモノです。

参照透過性:同じ引数なら必ず同じ戻り値になる
束縛:変数に一度代入した値後から変更できない

ゴッチャにならないよう気をつけましょう。

Discussion