---
breaks: false
tags: public-tech
---
# 関数型の読み方(単相の場合)
この記事は [OCaml Tips Advent Calendar 2022](https://adventar.org/calendars/8396) の18日目です。
OCaml での型の表記は C/C++ などのものとかなり異なっています。
例えば、OCaml で整数を 2 つ受け取り、それらを加算して返す関数 `add` は
次のような型を持ちます。
```ocaml
utop # let add n m = n + m;;
val add : int -> int -> int = <fun>
```
`int -> int -> int` は `int -> (int -> int)` と結合し
「整数を 1 つ受け取り『整数を 1 つ受け取り整数を返す関数』を返す関数」
を表しています。結局のところ 2 つ整数を引数として渡すと整数が返ってくるので、
2 引数関数だということになります。
原則として、OCaml では全ての関数型が 1 引数関数です[^one-argument]。つまり、関数型は必ず
`a -> b` のような形をしていて、引数として `a` 型の値を渡すと、`b` 型の値が
返ってくることを表します。先程の `add` の例では `a` が `int` で `b` が
`int -> int` になっていました。この構造を強調して `add` を定義することもできます。
```ocaml
(* add が
> 「整数を 1 つ受け取り『整数を 1 つ受け取り整数を返す関数』を返す関数」
であることを強調した定義 *)
let add = fun n -> fun m -> n + m
```
[^one-argument]: ただしこの構造のままアセンブリにコンパイルするとパフォーマンスが出ないので、コンパイラ内部では n 引数関数としてコンパイルされているはずです。
この構造を考慮すると、一部の引数だけ関数に与えて、その引数の値を固定したような
別の関数を作ることもできます。これを関数の部分適用といいます。
例えば `add` の 1 つ目の引数を `1` に固定して、1 引数関数 `add1` を作ることができます。
```ocaml
let add n m = n + m
let add1 = add 1 (* add の 1 つ目の引数を 1 に固定 *)
;;
assert (add1 3 = 4)
```