実際、理由はおそらく、<$>
と<*>
が1つの優先レベルを共有できるからです。我々は間違いなく<*>
が左結合することが
Prelude> foldr <$> [(+),(*)] <*> [0,1] <*> [[1,2,3], [4,5,6]]
[6,15,7,16,0,0,6,120]
作品のようなので、ものたい、これも<$>
は、それが高い優先順位を持っていないにもかかわらず、正しい方法を振る舞うことができます。実際に複数の<$>
演算子を連鎖することは、実際には左連想ではあまり役に立ちません。
ただし、右結合性ではあまり役に立ちません。。 chepnerがコメントしたように、実際にはちょっと面白く、$
は右結合である。確かに、それは
Prelude> sum $ map (+3) $ take 19 $ cycle [4..7]
160
のような組成物を書くことができますが、その後、ここで計算チェーンが解析されているので、これは単なるだけでなく、おそらくよりエレガント
Prelude> sum . map (+3) . take 19 . cycle $ [4..7]
160
(よりエレガントな私が言う、のように書くことができ命令型ではなく単一の機能パイプラインとして“これを実行してから、それを実行してください。”)。ファンクタの法則のおかげで、これは<$>
と.
と全く同じ方法で、$
と.
のようにすることができます。
マルチプル$
のスタイルを好む唯一の理由は、パイプライン内のインフィックスの表現を可能にする点です。最も一般的な例は、レンズの更新です(通常はフリップされた&
で書かれていますが、 ):$
と&
は、かなりはるかに低い任意の中置演算子よりも非常に低い優先度を持っているので
Prelude Control.Lens> [4..7] & ix 1+~9 & ix 2*~8
[4,14,48,7]
これは動作します。それはあなたがそのような場合には
Prelude Control.Lens> ix 1+~9 <$> [[4..8], [5..9]]
<interactive>:23:1: error:
Precedence parsing error
cannot mix ‘+~’ [infixr 4] and ‘<$>’ [infixl 4] in the same infix expression
を行うことはできません<$>
の場合ではないのです、あなた必要はとにかく、いくつかの括弧を使用するには、その後、あなたは同様に、低優先順位の合成作用素でそれを行う可能性がありますControl.Category
から:
Prelude Control.Lens Control.Category> (ix 1+~9 >>> ix 2*~8) <$> [[4..8], [5..9]]
[[4,14,48,7,8],[5,15,56,8,9]]
または各アップデータの周りの括弧付き:
Prelude Control.Lens> (ix 1+~9) . (ix 2*~8) <$> [[4..8], [5..9]]
[[4,14,48,7,8],[5,15,56,8,9]]
機能アプリケーションは、本質的である左連想。より良い質問はなぜ '$'が正しい連想であるかということでしょうか? – chepner
また、 'fmap'は、functionアプリケーションではなくfunction * lifting *と考えられます。 'fmap'が持ち上げられた関数を返すと、他の関数と同じように適用されます。特別なアプリケーションは必要ありません。 – chepner