最初のクールなことは、a -> b
サポートできることmap
です。はい、関数はファンクターです!
のタイプを考えてみましょうmap
:
map :: Functor f => (b -> c) -> f b -> f c
Functor f => f
具体的な型をArray
与えるために置き換えましょう:
map :: (b -> c) -> Array b -> Array c
今回Functor f => f
は次のように置き換えます。Maybe
map :: (b -> c) -> Maybe b -> Maybe c
相関関係は明らかです。バイナリ型をテストするためFunctor f => f
に, に置き換えましょう:Either a
map :: (b -> c) -> Either a b -> Either a c
a
関数の型をからb
として表現することがよくありますa -> b
が、それは の単なる砂糖ですFunction a b
。Either
長い形式を使用して、上記の署名をFunction
次のように置き換えましょう。
map :: (b -> c) -> Function a b -> Function a c
b -> c
したがって、関数をマッピングすると、元の関数の戻り値に関数を適用する関数が得られます。a -> b
砂糖を使用して署名を書き換えることができます。
map :: (b -> c) -> (a -> b) -> (a -> c)
何か気づきましたか?の型はcompose
何ですか?
compose :: (b -> c) -> (a -> b) -> a -> c
関数型に特化したcompose
だけです!map
2 つ目のクールな点は、a -> b
をサポートできることap
です。関数もアプリカティブ ファンクターです。これらはFantasy Land 仕様ではApplyとして知られています。
のタイプを考えてみましょうap
:
ap :: Apply f => f (b -> c) -> f b -> f c
Apply f => f
に置き換えましょうArray
:
ap :: Array (b -> c) -> Array b -> Array c
今、とEither a
:
ap :: Either a (b -> c) -> Either a b -> Either a c
今、とFunction a
:
ap :: Function a (b -> c) -> Function a b -> Function a c
とはFunction a (b -> c)
? 2 つのスタイルを混在させているので少し混乱しますが、type の値を取り、 from toa
の関数を返す関数です。スタイルを使って書き直してみましょう:b
c
a -> b
ap :: (a -> b -> c) -> (a -> b) -> (a -> c)
map
「持ち上げる」ことがap
できるあらゆるタイプ。見てみましょうlift2
:
lift2 :: Apply f => (b -> c -> d) -> f b -> f c -> f d
Function a
は Apply の要件を満たしているので、次のように置き換えることApply f => f
ができFunction a
ます。
lift2 :: (b -> c -> d) -> Function a b -> Function a c -> Function a d
どちらがより明確に書かれています:
lift2 :: (b -> c -> d) -> (a -> b) -> (a -> c) -> (a -> d)
最初の式をもう一度見てみましょう。
// average :: Number -> Number
const average = lift2(divide, sum, length);
何をしaverage([6, 7, 8])
ますか?a
( ) が関数 ( ) に[6, 7, 8]
与えられ、( )が生成されます。も関数 ( ) に与えられ、( ) が生成されます。これで aと aができたので、それらを関数 ( ) に渡して、最終結果である( ) を生成できます。a -> b
sum
b
21
a
a -> c
length
c
3
b
c
b -> c -> d
divide
d
7
したがって、Function 型はmap
およびをサポートできるため、( 、、およびを介して) 無料でap
取得できます。必要ないので、実際にはRamdaから削除したいと思います。converge
lift
lift2
lift3
converge
R.lift
この回答では意図的に使用を避けたことに注意してください。任意のアリティの関数をサポートするという決定により、意味のない型シグネチャと複雑な実装があります。一方、Sanctuary のアリティ固有のリフティング関数には、明確な型シグネチャと単純な実装があります。