簡體   English   中英

Haskell用於函數應用程序綁定的括號

[英]Haskell parentheses for function application binding

我正在學習Haskell。 我定義了以下函數(我知道我不需要addToList ,我也可以做無點符號我只是在玩語言概念):

map :: (a -> b) -> [a] -> [b]
map f []    = []
map f (x:xs)  = addToList (f x) map f xs
  where
    addToList :: a -> [a] -> [a]
    addToList x [] = [x]
    addToList x xs = x:xs

這會產生編譯錯誤:

with actual type `(a0 -> b0) -> [a0] -> [b0]'                                                                                                                   
Relevant bindings include                                                                                                                                                   
  f :: a -> b (bound at PlayGround.hs:12:5)                                                                                                                                 
  map :: (a -> b) -> [a] -> [b] (bound at PlayGround.hs:11:1)                                                                                                               
Probable cause: `map' is applied to too few arguments                                                                                                                       
In the second argument of `addToList', namely `map'                                                                                                                         
In the expression: addToList (f x) map f xs   

如果我在地圖周圍放置parantheses它的工作原理:

map :: (a -> b) -> [a] -> [b]
map f []    = []
map f (x:xs)  = addToList (f x) (map f xs)
  where
    addToList :: a -> [a] -> [a]
    addToList x [] = [x]
    addToList x xs = x:xs

我理解函數應用程序比運算符綁定更緊密(如Haskell中討論的那樣- 參數太少 ),但是,我不明白編譯器如何在沒有parantheses的情況下以不同方式解析上述內容。

看到錯誤的簡單方法是注意表達式:

addToList (f x) map f xs

將4個參數應用於addToList而:

addToList (f x) (map f xs)

將兩個參數應用於addToList (這是addToList “期望的”)。

更新

請注意,即使map有兩個參數,這個表達式:

addToList a map c d

被解析為:

(((addToList a) map) c) d

所以這里有一個可能的解釋GHC在想什么......

  1. addToList (fx)具有類型[a] -> [a] - 即它是一個獲取列表的函數。

  2. map有類型(c -> d) -> [c] -> [d] 它不是一個列表,但有了額外的參數,它可以產生一個列表。

  3. 因此,當GHC看到addTolist (fx) map並且無法鍵入檢查時,它會看到如果map只有一些參數,如下所示:

     addToList (fx) (map ...) 

至少addToList的第二個參數是一個列表 - 所以也許這就是問題所在。

解析是在進行類型檢查之前完成的一個獨特步驟。 表達方式

addToList (f x) map f xs

s1 (s2 s3) s4 s2 s5對解析器有同樣的意義。 它對名稱的含義一無所知。 它采用字符串的詞法結構並將其轉換為類似的解析樹

                        *5
                      /   \
                     /    xs
                    *4
                  /   \
                 /     f
                *3
              /   \
             /     map
            *2
          /   \
  addToList    *1
              / \
             f   x

解析樹完成后,每個節點都會標記其類型,並且可以進行類型檢查。 由於函數應用程序僅通過並置表示,因此類型檢查器知道節點的左子節點是函數,右子節點是參數,根節點是結果。

類型檢查器可以大致如下進行,對樹進行預先遍歷遍歷。 (我會略微改變類型簽名,以區分不相關的類型變量,直到它們統一起來。)

  1. addToList :: a -> [a] -> [a] ,所以它采用類型為a的參數並返回類型為[a] -> [a]的函數。 a尚不清楚。
  2. f :: b -> c ,所以它采用類型為b的參數並返回類型為c的值。 bc的值尚不清楚。
  3. x類型為d d的值尚不清楚。
  4. b ~ df可以應用於x ,所以*1 :: c
  5. a ~ caddToList應用於*1 ,所以*2 :: [a] -> [a]
  6. 哦,哦。 *2期望一個類型為[a]的參數,但它被應用於map :: (e -> f) -> [e] -> [f] 類型檢查器不知道如何統一列表類型和函數類型,這會產生您看到的錯誤。

暫無
暫無

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

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