#author("2019-08-06T23:53:48+00:00","default:sagasite","sagasite")
[[プログラミングの基礎]] > 第4章 関数の定義
*4.3 関数の型 [#mf637899]
OCamlは強く型付けされたプログラミング言語であり、プログラム中に現れるすべてのデータに型が付いています。
この性質は関数についても成り立っており、OCamlに出てくる関数にはすべて型が付いています。
**引数と返り値の型 [#jabf5017]
# let f x = 3 * x ;;
val f : int -> int = <fun>
「val f : int -> int = <fun>」というOCamlインタープリターの返答に注目します。
関数fは「int -> int」という型を持っています。
-1つ目のint=引数の型
-2つめのint=返り値の型
関数fは、整数型の引数を1個受け取り、整数型の返り値を1個返す、という形になっているので、関数fの型は「int -> int」となっているのですね。
関数の型の表記には、「->」という矢印記号が含まれていることが特徴です。
**返り値の型 [#a58c12ae]
# f 4 ;;
- : int = 12
関数fの返り値は整数型になっています。
整数4を3倍した答は、整数12です。
「 - : int = 12」は、12が整数型であることを示しています。
~
ここで注意したいのは、
-関数の型
-関数の返り値の型
は別物であり、混同しないようにするということです。
~
**<fun> [#lde4a5c9]
「<fun>」という記号、表記は、定義されたfが関数であることを示しています。
fun=function(関数)の省略ですね。
**引数が複数ある場合 [#z1cf77d7]
# let g x y = x * x + y * y - 4 ;;
val g : int -> int -> int = <fun>
# g 3 2 ;;
- : int = 9
引数が「x」と「y」の2個ある関数gを定義してみました。
関数gの型は「int -> int -> int」となっています。
intが3つになってますね。
~
これは、
-1つめのint=引数xの型
-2つめのint=引数yの型
-3つめのint=返り値の型
を表しています。
~
一般的に関数の型で、
A -> B -> C
となっていた場合、矢印記号は「右結合」になっています。
つまり、
(A -> B) -> C
ではなく、
A -> (B -> C)
という意味です。
これで、
1つ目の引数としてA型の値を受け取り、
2つ目の引数としてB型の値を受け取ったら、
結果としてC型の当たりを返す
という関数の型を表します。
***カリー化 [#q58491e1]
複数の引数を受け取る関数は、1個の引数を受け取る関数の組合せに分解できます。
関数型プログラミングの用語で、関数を分解することを「カリー化」と言います。
-[[カリー化 - Wikipedia>https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96]]
>カリー化 (currying, カリー化された=curried) とは、複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。
クリストファー・ストレイチーにより論理学者ハスケル・カリーにちなんで名付けられたが、実際に考案したのはMoses Schönfinkelとゴットロープ・フレーゲである。
ごく簡単な例として、f(a, b) = c という関数 f があるときに、F(a) = g(ここで、g は g(b) = c となる関数である)という関数 F が、f のカリー化である。
カリー化とは直感的には、&color(red){「関数の複数引数を、1引数ずつ順に、バラバラにする」};ということである。
A -> (B -> C)
は、「関数がカリー化できる(分解できる)」という意味も含まれている、と考えれば分かりやすいでしょうか?