OCaml一人勉強会 - 関数

リストやタプルの要素の弄り方がそこそこ分かったところで関数を。
int 型の引数に 1 を足した値を返すような関数は下のように書ける。

# fun x -> x + 1;;
- : int -> int = <fun>

まあ見たまんま。当然このままじゃ使えないので、変数に束縛しましょう。

# let succ = fun x -> x + 1;;
val succ : int -> int = <fun>
# succ 3;;
- : int = 4

シンタックスシュガーとして下のような書き方が出来ます。普通はそう書くらしい。

# let succ x = x + 1;;
val succ : int -> int = <fun>

次は int のリストの先頭の値を返す関数 head を定義しましょう。空の場合は 0 でも返しておくとして…

# let head list = match list with
  [] -> 0
  | hd :: rest -> hd;;
val head : int list -> int = <fun>
# head [1;2;3];;
- : int = 1

一般化した head も書きたいところですが残念なことに書けません。リストが空の時に返す値の型が問題になるため。
仕方がないので unit でも返そうとこんなコードを書くと…

# let head list = match list with
  [] -> ()
  | hd :: rest -> hd;;
val head : unit list -> unit = <fun>

unit のリストの先頭の値(勿論 unit に決まっている)を返す関数のできあがり!やった!
うれしくねえ!
ということで空のリストにも対応した head は書けません。*1標準ライブラリの List.hd も空リストを渡された時は例外を飛ばします。
さて、引数を一つとって match してどうこうする、というような関数を書く機会は頻繁にあって、そのたびにわざわざ引数名とか match とか with とか書くのはとてもだるい。そういう時のためのシンタクスシュガーが用意されています。

# let head = function
  [] -> 0
  | hd :: rest -> hd;;
val head : int list -> int = <fun>

function という予約語は若干長い気もしますが function タイピングで鍛えれば特に問題はないでしょう。

*1:まあ全然無理かというとそうでもなくて、任意の値か unit を取るようなバリアントで何とかすればその場は何とかなります。ただ、勿論返ってくるのはバリアントです。でバリアントの中の値が得たいとしてもそういう関数は同じ理由で書けないので…まあ…なんだ…諦めろ!