2012-11-18 67 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一样。