簡體   English   中英

Haskell運算符與函數優先級

[英]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.

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