2012-11-18 61 views
2

創建自己的數據類型,並嘗試執行函子方法如下:哈斯克爾仿錯誤

data Hieu a = Hieu [a] deriving (Show, Read, Eq) 

instance Functor Hieu where 
     fmap f (Hieu [x]) = Hieu (f [x]) 

這是非常簡單的代碼,但失敗了。你能解釋爲什麼嗎?


感謝您的回覆。現在我明白,我只適用於一種情況。我試圖改寫如下,而不使用地圖

data Hieu a = Hieu [a] deriving (Show, Read, Eq) 

consHieu :: a -> (Hieu a) -> (Hieu a) 
consHieu x (Hieu xs) = Hieu (x:xs) 

instance Functor Hieu where 
    fmap f (Hieu (x:xs)) = consHieu (f x) (fmap f (Hieu xs)) 
    fmap f (Hieu []) = Hieu [] 

感謝您的答覆。現在我明白,我只適用於一種情況。我試圖重寫爲跟隨,而無需使用地圖

數據總管Hieu一個=總管Hieu並[a]導出(顯示,讀取,等式)

consHieu ::一個 - >(總管Hieu一) - >(總管Hieu一)

consHieu X(總管Hieu XS)=總管Hieu(X:XS)

例如函子總管Hieu其中

fmap f (Hieu (x:xs)) = consHieu (f x) (fmap f (Hieu xs)) 
    fmap f (Hieu []) = Hieu [] 
+0

如果我們已經回答了您的問題並達到您的滿意度,請接受其中一個答案(單擊您希望接受的答案左側的複選標記)。如果還有一點您不清楚,請明確說明您不瞭解的內容,並明確要求提供幫助。 – dave4420

回答

6

f [x]你申請f到列表中的表達式,但這是不允許的,因爲fmap的類型簽名是(a -> b) -> Hieu a -> Hieu b。您不允許將f限制爲[a] -> [b]

也許你的意思是寫

instance Functor Hieu where 
    fmap f (Hieu [x]) = Hieu [f x] 

這將編譯,但如果列表中的一個元素,將只工作。使Hieu函子的方式,一般是使用map的功能適用於所有的元素,像這樣:

instance Functor Hieu where 
    fmap f (Hieu xs) = Hieu (map f xs) 
4

你只處理一個案件,一個元素的列表,並處理它不正確。類型級別[a](任何長度爲a的列表的類型)與值級別[x](包含一個元素的列表完全相同,名爲x)有很大不同!

正確的實例將涉及以更多涉及的方式使用該函數。

fmap :: (a -> b) -> Hieu a -> Hieu b 
fmap f (Hieu xs) = Hieu (`...`) 

...,我們有f :: a -> bxs :: [a],我們想要的東西:: [b]。有一種自然的方法可以實現 - 將函數映射到列表上。

因此,一個正確的實例將如下所示:

instance Functor Hieu where 
    fmap f (Hieu xs) = Hieu (map f xs) 

任何其他實例 - 例如,一個只處理一個元素的列表 - 不服從函子法律,因爲我們希望fmap id h到總是和h一樣。