h1 f g x y = f (g x y) x
したがって、引数リストを左から右に取得します。
f
は2つの引数に適用される関数です。1つ目はの結果で(g x y)
、2つ目はの結果です。x
- 最初の引数がどのタイプかはまだわからないので、それを呼び出しましょう
a
- 2番目のタイプもわからないので、それを呼びましょう
b
- また、結果のタイプもわかりません(したがって、これを呼び出します
c
)が、これはによって返されるタイプである必要があることはわかっています。h1
g
は2つの引数に適用される関数です:最初の引数x
と2番目の引数y
- の最初の引数
g
はの2番目の引数と同じであるf
ことがわかっているので、同じタイプである必要があります。b
- の2番目の引数
g
はですy
。これはまだプレースホルダータイプを割り当てていないため、次の引数を順番に取得します。d
g
の結果はへの最初の引数f
であり、すでにそれをラベル付けしていますa
- これ
g
で関数マッピングになりますb -> d -> a
- 3番目の引数はです。これ
x
はの2番目の引数なのでf
、すでにその型にラベルを付けています。b
- 4番目の引数は
y
、の2番目の引数であるため、その型g
にはすでにラベルが付けられていますd
- の結果は、前に述べたように、
h1
に適用f
した結果であるため、同じタイプであり、すでにラベルが付けられています(g x y) x
c
引数リストを順番に調べましたが、これらの各引数の型のラベル付け、推測、および統合の実際のプロセスは、の本体を調べることによって行われましたh1
。
したがって、私の最初の弾丸は次のように詳しく説明できます。
f
を検討する最初の引数なので、h1
(の後にあるすべての=
)の本体を見て、それがどのように使用されているかを
見てみましょう。
f (g x y) x
f
に適用されることを意味する(g x y) x
のでf
、関数である必要があります
(g x y)
は括弧内にあります。これは、それらの括弧内にあるものはすべて評価されていることを意味し、その評価の結果は次の引数になります。f
x
の単純な引数であり、の独自の引数リストf
から直接渡されますh1
- つまり、
f
2つの引数を取る関数です
読みやすくなる場合はf (g x y) x
、Cのような表記法での同等の式は。と見なすことができますf(g(x,y), x)
。f
ここでは、とg
が2つの引数を取る関数であることがすぐにわかります。f
最初の引数は、g
返されるものなどです。
式の左側の、はh1 f g x y
、それ自体で1つの型情報のみを提供することに注意してくださいh1
。は4つの引数の関数です。引数名自体は、式の右側(の本体h1
)で使用される単なるプレースホルダーです。ここでの引数の相対的な順序は、を呼び出す方法を示しているだけですが、引数を内部でどのように使用するかについては何もh1
示していません。h1
繰り返しになりますが、これは手続き型の同等物です(Pythonを使用するので、タイプを入力する必要はありません):
def h1(f, g, x, y):
return f(g(x,y),x)
これはまったく同じ意味です
h1 f g x y = f (g x y) x
(1つの警告-部分適用-ここで問題をさらに混乱させるだけだと私は思う)。
どちらの場合も、宣言(=
Haskellでは左:
、Pythonでは前)は関数名とそれが取る引数の数だけを教えてくれます。
どちらの場合も、定義(Haskellの右側、Pythonの後にインデントされたブロック)から、両方とも2つの引数の関数であり、最初の引数は2番目の引数と同じであると推測できます。Haskellでは、コンパイラがこれを行います。間違った数の引数で呼び出すと、Pythonは実行時に文句を言うだけです。そうしないと、最初の引数として使用できないものが返されます。:
f
g
g
f
g
f