関数の型註釈

関数定義の時に型を明示しなくても推論で型を決めてくれるけど、明示したいこともある。
例えば、** 演算子は float 型専用なので他の型では使えない。

let pow x y =
    x ** y
pow "2" "10"
//=> error FS0001: This expression was expected to have type float but here has type string

そこで型註釈が必要なのだが。

let pow (x:string) (y:string) =
    (float x) ** (float y)
    |> string
pow "2" "10"   //=> "1024"

期待通りには動くが、pow の定義の型註釈がとても見にくい。
引数ひとつひとつに註釈するのではなく、関数全体の型をまとめてかければその方が見やすかろう。その方法もある。
F# では変数の型註釈を

let x : int = 42

という風に識別子と値の間に書くことができる。
そして関数もファーストクラスであり、無名関数を識別子に束縛することで関数定義ができるわけで、要するに変数と同じように関数も型註釈ができる。

let pow : string -> string -> string =
    fun x y ->
        (float x) ** (float y)
        |> string

ちょっと haskell に似てる。まず関数の型を記述してその後に定義を記述する。
この記法なら型註釈も億劫じゃない。
ただ、一つ前に書いた「引数に個別に型註釈を付けたコード」と比べると「fun x y ->」が入る分、インデントが1つ深くなってしまう。
それが嫌なら一応これでもいける。

let pow : string -> string -> string =
fun x y ->
    (float x) ** (float y)
    |> string

let と fun は同じインデントレベルになってもいいみたい。流石にこれは抵抗あるかな? 慣れりゃなんてことないと思うけど...

ちょっと変えた

本文のコード int だと話がややこしくなるので、string にしました。

最後のはよくないみたい

上の最後のコードはコンパイラがワニングだしてました。

warning FS0058: Possible incorrect indentation: this token is offside of context started at position (18:1). Try indenting this token further or using standard formatting conventions.

エラーではなく警告なのでコンパイルはされますが、よくないみたいです。