簡體   English   中英

類型聲明有什么問題嗎?

[英]Anything wrong with the type declaration?

我正在閱讀“Haskell編程”一書。 一個練習要求我使用高階函數定義map f 我選擇定義map (+1) ,如下所示:

unfold p h t x | p x       = []
               | otherwise = h x : unfold p h t (t x)

-- equivalent to `map (+1)`
mapinc = unfold (==[]) ((+1).head) tail

(直接來自練習題)如果謂詞p為參數值為true,則函數unfold pht生成空列表,否則通過將函數h應用於此值來生成非空列表以給出頭部,並且function t生成另一個參數,以相同的方式遞歸處理以生成列表的尾部。

我檢查了mapinc實現,看起來很好:

*Main> mapinc [1,2,3]
[2,3,4]

但是,在我添加類型聲明后:

mapinc :: Num a => [a] -> [a]
mapinc = unfold (==[]) ((+1).head) tail

然后在WinGHCi中重新加載腳本,它會出現以下錯誤:

• Could not deduce (Eq a) arising from a use of ‘==’
  from the context: Num a
    bound by the type signature for:
               mapinc :: forall a. Num a => [a] -> [a]
    at D:\7a.hs:4:1-29
  Possible fix:
    add (Eq a) to the context of
      the type signature for:
        mapinc :: forall a. Num a => [a] -> [a]
• In the first argument of ‘unfold’, namely ‘(== [])’
  In the expression: unfold (== []) ((+ 1) . head) tail
  In an equation for ‘mapinc’:
      mapinc = unfold (== []) ((+ 1) . head) tail
  |
5 | mapinc = unfold (==[]) ((+1).head) tail   |                  ^^^^

任何線索為什么會發生?

你的簽名太寬泛了 你寫的謂詞是== [] Haskell只能檢查兩個列表是否相等,是否也可以檢查列表的元素 在源代碼中我們看到類似於:

instance Eq a => Eq [a] where
    ...

是的,在這里我們永遠不會檢查兩個項目的相等性,因為我們檢查空列表,但編譯器當然不知道:它只是看到為了檢查兩個列表是否相等,我們需要能夠檢查元素是否相等。

Num類型類並不意味着該類型也是一個Eq類型。 我們可以在這做兩件事:

  1. Eq類型約束添加到簽名:

     mapinc :: (Eq a, Num a ) => [a] -> [a] mapinc = unfold (==[]) ((+1).head) tail 
  2. 更優雅:不要依賴於我們需要能夠比較元素的事實,而是使用null :: [a] -> Bool (一個檢查列表是否為空的函數):

     mapinc :: Num a => [a] -> [a] mapinc = unfold null ((+1).head) tail 

暫無
暫無

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

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