関数適用がhaskellでのカリー化でどのように機能するかを理解するのに問題があります。次の機能がある場合:
($) :: (a -> b) -> a -> b
この関数を部分的に適用するには、(a -> b)
関数($
の最初の引数)を提供する必要があることを理解しています。
では、なぜ最初に値を適用できるのでしょうか(つまり、逆引数)?
($ 0) :: Num a => (a -> b) -> b
ここで何が欠けていますか?
関数適用がhaskellでのカリー化でどのように機能するかを理解するのに問題があります。次の機能がある場合:
($) :: (a -> b) -> a -> b
この関数を部分的に適用するには、(a -> b)
関数($
の最初の引数)を提供する必要があることを理解しています。
では、なぜ最初に値を適用できるのでしょうか(つまり、逆引数)?
($ 0) :: Num a => (a -> b) -> b
ここで何が欠けていますか?
($)
は演算子です。Haskellでは、どの演算子も左セクション(のような(x $)
)または右セクション(のような)で書くことができます($ x)
:
(x $) = (\y -> x $ y) = ($) x
($ x) = (\y -> y $ x) = flip ($) x
この規則の唯一の例外は(-)
、負の数を便利に書くために、です。
\x -> (x-) :: Num a => a -> a -> a -- equivalent to \x -> (-) x
\x -> (-x) :: Num a => a -> a -- equivalent to \x -> negate x
簡潔に書きたい場合は(\y -> y - x)
、以下を使用できますsubtract
。
\x -> subtract x :: Num a => a -> a -> a -- equivalent to \x -> flip (-) x
($ 0)
≡≡ (\x -> x $ 0)
_(\x -> ($) x 0)
もし私たちが持っている($) :: (a -> b) -> a -> b)
ように2番目の引数を適用した場合(\x -> ($) x 0)
:: Num a => (a -> b) -> b
演算子のインフィックス表記と関数を混同しています。
> :t (($) (+1))
(($) (+1)) :: Num b => b -> b
$
理解を深めるために、を使用した式のいくつかの形式を次に示します。
a $ b =>($)ab
($ b)=>フリップ($)b =>(\ ba->($)ab)b => \ a->($)ab
(a $)=>($)a => \ b->($)ab
Haskell構文では、英数字の名前は句読点の名前と区別されることにも注意してください。
英数字関数foo1 a b
はデフォルトで接頭辞であり、バッククォートを追加すると中置になりますa `foo` b
。
$
またはのような句読点の名前が付いた関数<*>
は、デフォルトでは中置であり、括弧($)
またはを追加すると接頭辞になります(<*>)
。これは、ラテンアルファベットに精通しているプログラマーにとっては単なる構文糖衣です。これは、英数字の名前と句読点の名前を任意に区別するのに役立ちます。
どちらの種類の関数も単なる関数であり、C++またはJavaの「演算子」にあるような特別なセマンティックルールはありません。句読点の名前が付けられた関数と英数字の名前が付けられた関数で異なるのは、接頭辞/中置と後括弧/括弧に関する構文規則だけです。