F# メモ 関数
定義
2つの int を引数に取り、その和を返す関数 add は以下のように表す。
> let add a b = a + b;;
val add : int -> int -> int
val add : int -> int -> int
実行してみる。
> add 1 2;;
val it : int = 3
val it : int = 3
関数の型
float -> int は 「float を引数に取り、int を返す関数」と読む。
上の add の場合 int -> int -> int が関数の型で、「intを引数に取り、「intを引数に取り、intを返す関数」を返す関数」と読む。
型推論
上の add 関数のように引数の型が複数考えられるとき、最初に使用されたときの引数を基に関数の型が決まる。(ただし、対話モードでは一旦 ;; で終了した時点で確定する)
> add 1.0 2.0;;
add 1.0 2.0;;
----^^^
stdin(3,5): error FS0001: This expression was expected to have type
int
but here has type
float
add 1.0 2.0;;
----^^^
stdin(3,5): error FS0001: This expression was expected to have type
int
but here has type
float
のように float を引数とすることはできない。
これは関数 add が int -> int -> int と推論されているため。
float のみを渡せるようにするには、以下のように明示的に型を指定する。
> let addf (a:float) b = a + b;;
val addf : float -> float -> float
> addf 1.0 2.0;;
val it : float = 3.0
val addf : float -> float -> float
> addf 1.0 2.0;;
val it : float = 3.0
ジェネリック関数
‘a のように ‘ を付けた型を指定すると、どんな型でも引数に取ることができる関数を作ることができる。
‘a でも ‘b でも ‘asdfghjk でもいいらしい。
> let str (x:'a) = x.ToString();;
val str : 'a -> string
> str(10);;
val it : string = "10"
val str : 'a -> string
> str(10);;
val it : string = "10"
スコープ
F#のスコープはインデントで表される。
全くインデントされていないスコープがモジュールスコープ。
> let Pow2 x =
let value = x * x
value;;
val Pow2 : int -> int
> Pow2 10;;
val it : int = 100
let value = x * x
value;;
val Pow2 : int -> int
> Pow2 10;;
val it : int = 100
関数スコープの最後に評価された値がその関数の戻り値となる。

rei@sikios.com
こんにちは。
一箇所気になったところがあります。
> 上の add の場合 int -> int -> int が関数の型で、
> 「「int を引数に取り、int を返す関数」を引数に取り、int を返す関数」と読む。
この意味だと
(int -> int) -> int
と書くことになりますが、
add の型は括弧を補うと
int -> (int -> int)
となります。(カリー化関数)
ですので、
「intを引数に取り、「intを引数に取り、intを返す関数」を返す関数」と読むのが正しいかと思います。
ご指摘ありがとうございます。
訂正させて頂きます。
> let add_base a b = a + b
let add_curry a = add_base a
let x = add_curry 1 2;;
val add_base : int -> int -> int
val add_curry : int -> (int -> int)
val x : int = 3
きっとこういうことだと思います。
はじめての関数型言語なので、カリー化というものがまだ感覚的に馴染んでいないのですが、慣れれば自然に感じるようになるんでしょうね。