為了說明函式應用在 Haskell 中具有最高優先級,提供了以下示例(由 schoolofhaskell 提供):
sq b = b * b main = print $ -- show sq 3 1 -- /show
這里的結果是 10。
令我困惑的是,該引數也構成了一個函式應用程式。將運算子 視為函式的快捷方式。因此,當采用引數時,我希望它的函式應用現在優先于原始應用。
以這種方式撰寫它可以提供預期的結果:
sq b = b * b
main = print $
sq (( ) 3 1 )
有什么解釋嗎?
uj5u.com熱心網友回復:
令我困惑的是,該引數也構成了一個函式應用程式。考慮運算子“ ”是函式的快捷方式。
我認為這是這里所涉及的誤解的核心(實際上,非常好的理解!)。確實,這是3 1一個表示( )函式應用于3and的運算式1,您已經正確理解了這一點。但是,Haskell 有兩種函式應用語法,前綴和中綴。因此,“函式應用程式具有最高優先級”的更精確版本將類似于“語法前綴函式應用程式具有比任何語法中綴函式應用程式更高的優先級”。
您還可以在兩種形式之間來回轉換。每個函式都有一個“自然”的位置:只有符號的名稱自然是語法中綴,帶有字母和數字等的名稱自然是語法前綴。您可以將自然前綴函式轉換為帶有反引號的中綴,并將自然中綴函式轉換為帶有括號的前綴。所以,如果我們定義
plus = ( )
那么以下所有內容實際上都意味著同一件事:
3 1
3 `plus` 1
( ) 3 1
plus 3 1
回到你的例子:
sq 3 1
因為sq是自然前綴, 自然是中綴,所以sq應用程式優先。
uj5u.com熱心網友回復:
因此,當采用引數時,會期望其函式應用現在優先于原始應用。
Haskell 語法 [Haskell 報告]指定:
經驗10 → … | … | fexp fexp → [fexp] aexp(函式應用)
這意味著函式應用程式語法的優先級為 10(部件上的上標)。exp10
這意味著,當您的運算式被決議時,空格 insq 3優先于 in 3 1,因此在語意sq 3 1上被解釋為(sq 3) 1它3首先平方,然后添加1到結果中,從而產生10.
如果你把它寫成sq (3 1)或 以規范形式,因為sq (( ) 3 1)它會首先求和3,1然后確定將產生的平方16。
uj5u.com熱心網友回復:
加法運算子在語法上與函式應用程式不同,這決定了它的運算子優先級。
如果您將添加重寫(3 1)為函式應用程式(( ) 3 1),則切片在其自己的括號內( )遵循特殊的切片規則,但在切片之外它只是另一個帶括號的運算式。
請注意,您的“預期結果”與您的原始示例并不真正平行:
sq 3 1 -- original example, parsed `(sq 3) 1`
sq (( ) 3 1) -- "expected result", has added parentheses to force your parse
sq (3 1) -- this is the operator version of "expected result"
在 Haskell 中,括號不是函式應用程式的一部分——它們僅用于分組!
也就是說:like( )只是另外一個帶括號的運算式,so is(3 1)
uj5u.com熱心網友回復:
我認為您的困惑只是語言稍微不精確的結果(在 OP 和 Haskell 頁面鏈接的部分)。
當我們說“函式應用比任何運算子具有更高的優先級”之類的東西時,術語“函式應用”實際上并沒有一個短語意味著“應用函式”。它是特定句法形式的名稱func arg(您只需將兩個術語并排寫下,以便將第一個應用于第二個)。我們試圖區分應用函式的“普通”前綴語法和應用函式的中綴運算子語法。因此,對于這種特定用法,sq 3是“功能應用程式”而3 1不是。但這并不是說這sq是一個功能, 而不是!
而在許多其他情況下,“功能應用”確實意味著“應用功能”;它不是一個單獨的術語,而是恰好一起使用的“功能”和“應用程式”這兩個詞的普通含義。從這個意義上說,兩者都是 “功能應用”的例子。sq 33 1
該術語的這兩種含義之所以出現,是因為我們在考慮代碼1時使用了兩種不同的背景關系:邏輯和句法。考慮我們是否定義:
add = ( )
在我們考慮由代碼表示的理想化數學物件的“邏輯”視圖中,兩者add都是( )簡單的函式(實際上是相同的函式)。它們甚至是完全相同的物件(我們通過說它等于另一個來定義一個)。這個潛在的數學函式獨立于任何名稱而存在,并且無論我們如何選擇參考它都具有完全相同的屬性。特別是,可以應用函式(因為這基本上是函式的唯一定義特征)。
但是在句法級別上,該語言對于如何使用名稱 add和 (無論這些名稱所指的底層物件如何)有不同的規則。這些名稱之一是運算子,另一個不是。我們對如何撰寫運算子的應用程式有特殊的語法規則,這不同于您需要撰寫任何非運算子術語的應用程式(包括但不限于非運算子名稱,如sq2)。因此,在談論語法時,我們需要能夠區分這兩種情況。但重要的是要記住這是名稱和語法的區別,并且與所參考的底層函式無關(事實證明,完全相同的函式在程式的不同部分可以有許多名稱,其中一些是運算子,而另一些則不是)。
對于“任何不是運營商的術語”,實際上并沒有商定的通用術語;如果有,我們可能會說“非運算子應用程式的優先級高于任何運算子”,因為這樣會更清楚。但無論好壞,“通過簡單鄰接應用”句法特征經常被稱為“函式應用”,盡管該術語在其他背景關系中也可能意味著其他事物3。
所以(不?)幸運的是,這里沒有比“函式應用”這個短語在不同的背景關系中表示不同的東西更深層次的事情了。
1好的,我們可以使用兩種以上的背景關系來考慮我們的代碼。有兩個與我要提出的觀點相關。
2對于可以應用的其他非運算子術語的示例,我們也可以在括號中使用任意運算式。例如(compare on是to fst) (1, ())的非運算子應用程式;被應用的運算式本身就是to和的運算子應用程式。(compare `on` fst)(1, ())oncomparefst
3 For yet another usage, $ is often deemed to be the "function application operator"; this is perhaps ironic when considered alongside usages that are trying to use the phrase "function application" specifically to exclude operators!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/427277.html
