def f1 (n:Nat) (m:Nat) : Nat := n + m def f2 (n:Nat) : Nat → Nat := fun (m:Nat) => n + m def f3 : Nat → Nat → Nat := fun (n :Nat) => fun(m:Nat) => n + m def f4 : Nat → Nat → Nat := fun (n m:Nat) => n + m #check f1 #check f2 #check f3 #check f4 #eval f1 3 4 #eval f2 3 4 #eval f3 3 4 #eval f4 3 4
check による表示では:
- f1 (n m : Nat) : Nat
- f2 (n _a : Nat) : Nat
- f3 (_a _a1 : Nat) : Nat
- f4 (_a _a1 : Nat) : Nat
ここで、アンダースコア始まり変数は、もとラムダ変数。シーケント記法だと:
- f1 : (n m : Nat) |- Nat
- f2 : (n _a : Nat) |- Nat
- f3 : (_a _a1 : Nat) |- Nat
- f4 : (_a _a1 : Nat) |- Nat
つまり、フル・アンカリー化して表示する。だが、内部的にはフルカリー化している。
- f1 : |- Nat → Nat → Nat
- f2 : |- Nat → Nat → Nat
- f3 : |- Nat → Nat → Nat
- f4 : |- Nat → Nat → Nat
よって、内部的はすべての関数は同じ形式になっていて区别が付かない(名前が異なるだけ)。呼び出し形式も戻り値も同じになる。次の点が分かりにくい。
- 表示はフル・アンカリー化する。
- 内部的な格納形式はフル・カリー化する。
- 呼び出しは、フル・カリー化関数を呼び出す。
def s1 (n: Nat) : Nat := n + 1 def s2 : Nat → Nat := fun (n:Nat) => n + 1 #check s1 #check s2 def valAtZero (f:Nat → Nat) : Nat := f 0 def valAtZero2 : (Nat → Nat) → Nat := fun (f:Nat → Nat) => f 0 #check valAtZero #check valAtZero2 #eval valAtZero s1 #eval valAtZero s2 #eval valAtZero2 s1 #eval valAtZero2 s2
↑で、定義形式に関わらずフルカリー化関数が格納されて呼び出されることが分かる。表示においては定義形式の影響を受けるが、内部に格納されている関数自体は定義形式の影響を受けない。
そもそも、インラインで関数を書くときは、フルカリー化する以外の方法がない。