[英]Haskell operator vs function precedence
我正在嘗試為自己驗證Haskell中的運算符和函數優先級。 例如,以下代碼
list = map foo $ xs
可以改寫為
list = (map foo) $ (xs)
並最終將成為
list = map foo xs
我的問題曾經是,為什么第一個表述不會被重寫為
list = (map foo $) xs
因為函數優先級總是高於運算符優先級,但我認為我找到了答案:運算符根本不允許作為函數的參數(當然,除非用括號括起它們)。 這是正確的嗎? 如果是這樣的話,我覺得很奇怪,在RWH中沒有提到這個機制/規則或者學習一個Haskell,或者我搜索過的任何其他地方。 因此,如果您知道規則所在的地方,請鏈接到該地址。
- 編輯:感謝您的快速解答。 我認為我的困惑來自於認為運算符字母會以某種方式評估某些東西,這可能會被函數作為參數使用。 它幫助我記住,一個中綴運算符可以機械地轉換為前綴函數。 對第一個配方這樣做會產生
($) (map foo) (xs)
毫無疑問,($)是消耗函數,並且由於兩個公式是等價的,因此第一個公式中的$ literal不能被map使用。
首先,應用程序(空白)是最高優先級的“運算符”。
其次,在Haskell中,運算符和函數之間並沒有區別,除了默認情況下運算符是中綴,而函數不是。 您可以使用反引號將函數轉換為中綴
2 `f` x
並將運算符轉換為帶有parens的前綴:
(+) 2 3
所以,你的問題有點困惑。
現在,特定的函數和運算符將聲明優先級,您可以在GHCi中找到“:info”:
Prelude> :info ($)
($) :: (a -> b) -> a -> b -- Defined in GHC.Base
infixr 0 $
Prelude> :info (+)
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
infixl 6 +
顯示優先級和關聯性。
你是對的。 此規則是Haskell報告定義的Haskell語法的一部分。 特別注意在第3節“表達式”中,函數應用程序( fexp
)的參數必須是aexp
。 aexp允許運算符作為節的一部分,也可以在帶括號的表達式中,但不允許運算符。
在map foo $ xs
,Haskell語法意味着將其解析為應用於二元運算符$
兩個表達式。 正如sepp2k所說,語法(map foo $)
是左側部分,具有不同的含義。
我必須承認,我從來沒有想過這個,實際上我必須在報告中查一查,看看為什么運營商會采取行動。
除了已經由其他答案提供的信息之外,請注意,不同的運算符可以具有與其他運算符不同的優先級,以及左/右或非關聯。 您可以在Haskell 98報告固定性部分中找到Prelude
運算符的這些屬性。
+--------+----------------------+-----------------------+-------------------+ | Prec- | Left associative | Non-associative | Right associative | | edence | operators | operators | operators | +--------+----------------------+-----------------------+-------------------+ | 9 | !! | | . | | 8 | | | ^, ^^, ** | | 7 | *, /, `div`, | | | | | `mod`, `rem`, `quot` | | | | 6 | +, - | | | | 5 | | | :, ++ | | 4 | | ==, /=, <, <=, >, >=, | | | | | `elem`, `notElem` | | | 3 | | | && | | 2 | | | || | | 1 | >>, >>= | | | | 0 | | | $, $!, `seq` | +--------+----------------------+-----------------------+-------------------+
假定缺少固定性聲明的任何運算符與優先級9保持關聯 。
請記住,函數應用程序具有最高優先級(考慮優先級10
與表中的其他優先級相比) [1] 。
不同之處在於中綴運算符放在它們的參數之間,所以這個
list = map foo $ xs
可以用前綴形式重寫為
list = ($) (map foo) xs
根據$運算符的定義,它就是簡單的
list = (map foo) xs
如果用括號括起運算符(即map foo ($) xs
,它們確實會傳遞給(map foo ($)) xs
),那么運算符可以作為函數參數傳遞。 但是,如果不用括號括起它們,那么它們是正確的,它們不能作為參數傳遞(或分配給變量)。
還要注意語法(someValue $)
(其中$
可以是任何運算符)實際上意味着不同的東西:它相當於\\x -> someValue $ x
,即它部分地將運算符應用於其左操作數(在$
情況下)當然是noop)。 同樣($ x)
將運算符部分應用於右操作數。 因此map ($ x) [f, g, h]
將評估為[fx, gx, hx]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.