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 []

感谢您的所有回复。现在我明白了我只将仿函数应用于一种情况。我试图重写如下,不使用地图

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

consHieu :: a -> (Hieu a) -> (Hieu a)

consHieu x (Hieu xs) = Hieu (x:xs)

实例 Functor Hieu 在哪里

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

2 回答 2

6

f [x]在您应用于列表的表达式f中,但这是不允许的,因为fmapis的类型签名(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)
于 2012-11-18T03:31:20.287 回答
4

您只处理一个案例,一个单元素列表,并且处理不正确。类型级别[a](任何长度 s 的列表的类型)与值级别(仅包含一个元素的列表,称为)a非常不同![x]x

正确的实例将涉及以更复杂的方式使用该功能。

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

..., 我们有f :: a -> b并且xs :: [a]我们想要一些东西:: [b]。有一种自然的方法可以得到它——将函数映射到列表上。

所以一个正确的实例看起来像:

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

任何其他实例——例如,只处理单元素列表的实例——都不会遵守 Functor 定律,因为我们希望fmap id h始终与h.

于 2012-11-18T03:32:23.487 回答