2013-06-21 60 views
3

請解釋Haskell如何確定帶有多個參數和多個部分應用函數的部分的優先級。有時我發現很難弄清楚當整個表達式需要多個參數時哪個部分函數會應用哪個參數。瞭解Haskell優先級規則如何與多個部分應用程序一起工作

以下是一些示例函數,但我確定不同的示例可以更具說明性。第一個來自「應用程序編程與效果」文章。

sequence :: [IO a] → IO [a] 
sequence [] = return [] 
sequence (c : cs) = return (:) `ap` c `ap` sequence cs 

(.) (.) 
(.) (.) (.) 

是否有工具將此類表達式轉換爲lambda表達式形式?

+0

如果您在#haskell IRC頻道的時候,你可以使用@unpl ,它將無點的版本轉換爲點(ful)(lambda)版本。 (。)(。)(。)的例子:(\ c e f i - > c(e f i)) – bennofs

回答

3

標識符像a b c d被解析爲(((a b) c) d)功能的應用列表。帶圓括號的中綴運算符(.)被視爲標識符。

所以(.) (.) (.)解析爲((.) (.)) (.)

通常,可變操作者這樣

`functionname` 

默認已經離開結合性,和比功能應用的優先級較低,不過這可以通過一個或infixl聲明infixr進行修改。該ap功能尚未從默認的修改,所以sequence pases的RHS爲:

((return (:)) `ap` c) `ap` (sequence cs) 

或等價

ap (ap (return (:)) c) (sequence cs) 
+0

「函數應用程序的優先級低於函數應用程序,但這個可以修改」的句子有點尷尬,可以像讀取「中綴」聲明比函數應用程序的優先級更高。 –

+0

爲什麼'(return(:))'ap'''不是''應用''返回(:)'而是作爲一個段讀取?部分是否像這裏一樣「翻譯」爲「ap(return(:))」? – Rumca

+0

@Rumca我不知道你在這裏的「部分」是什麼意思。 (x \'f \'y)解析爲'fxy',並且x \'''''''''\ z解析爲(x \'f \'y)\'f \'z或'f (fxy)z'。至於爲什麼,我只能參考[The Haskell Report](http://www.haskell.org/definition/haskell98-report.pdf),第3.2節。 – NovaDenizen

8

括號中的運算符參數被視爲正常標識符。因此,(+)add的行爲方式完全相同。這意味着它在前綴形式中使用,並且優先級問題根本不會出現。記住

這樣,我們可以想像寫以下內容:

compose = (.) 
compose compose compose 

後者的版本是一樣的使用(.)混亂的版本。它有助於記住該功能的應用程序是正確的關聯,所以表達式是一樣的:

(compose compose) compose 

與參數的操作部分,像(+ 1)(1 +)也表現就像儘可能優先關注正常標識符。所以如果你定義了next = (+ 1),兩者都會表現相同。

就無點代碼而言,pointful程序包有一個命令行工具,它需要一個免費函數並嘗試將它變成一堆lambdas。您還可以從@unpl的#haskell IRC頻道的lambdabot中獲得此功能。

你可以只安裝貼題與陰謀,並稱之爲:

cabal install pointful 
pointful 
+0

由於compose有兩個參數,它爲什麼不能解析成'(compose compose compose)? – Rumca

+6

@Rumca在Haskell中,每個函數都只需要一個參數。有些人,比如'compose',然後返回一個接受另一個參數的函數。 –