簡體   English   中英

為什么 <$> 是左結合的?

[英]Why is <$> left associative?

fmap也是<$>因為它是函子類別中的函數應用程序( $ )。

(+5)  $  (*10)  $  10      -- 105
(+5) <$> (*10) <$> [1,2,3] -- [15,25,35]

然后我想,在那種情況下<*>是 applicative functor 類別中的函數應用程序,這應該可以工作:

[(+5), (+10)] <*>  [(*10), (*100)] <*> [1,2,3]  -- ERROR
-- however:
[(+5), (+10)] <*> ([(*10), (*100)] <*> [1,2,3]) -- [15,25,35,...]

所以, <$>之所以有效,是因為函數的fmap恰好是后組合,所以(+5) <$> (*10)變成(+5) . (*10) (+5) . (*10)然后應用於[1,2,3]

然而,所有應用程序運算符(包括<<= )的左結合在我看來是一個糟糕的設計選擇,尤其是在他們認識到與$的相似性之后,這已經是右結合了。 還有其他原因嗎?

真的,原因可能只是它允許<$><*>共享一個優先級。 我們肯定希望<*>是左關聯的,比如

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

(我說得更優雅,因為這里的計算鏈被解析為一個單一的功能管道,而不是命令式的“做這個,然后那個,然后……”)。 由於函子定律,這可以通過<$>. $. .

您可能更喜歡 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]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM