实际上,原因可能只是它允许<$>
并<*>
共享一个优先级。我们绝对希望<*>
成为左联想,所以像
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
(我说得更优雅,因为这里的计算链被解析为单个功能管道,而不是命令式的“做这个,然后那个,然后......”)。由于函子定律,这可以用 and 和 and 一样的<$>
方式.
完成。$
.
您可能更喜欢 multiple- 样式的唯一原因$
是它允许在管道中使用中缀表达式,也许最常见的示例是镜头更新(通常用翻转的 编写&
,但原理是相同的):
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]]