[英]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
類型。 我們可以在這做兩件事:
將Eq
類型約束添加到簽名:
mapinc :: (Eq a, Num a ) => [a] -> [a] mapinc = unfold (==[]) ((+1).head) tail
更優雅:不要依賴於我們需要能夠比較元素的事實,而是使用null :: [a] -> Bool
(一個檢查列表是否為空的函數):
mapinc :: Num a => [a] -> [a] mapinc = unfold null ((+1).head) tail
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.