Haskell fmap函数

Haskell fmap functor

我对基于指定代数数据结构的队列上的函子有疑问。

data DQueue a = Empty | Enqueue a (DQueue a)
    deriving (Eq, Show, Read)


instance Functor DQueue
  where
    fmap f (Enqueue x xs) = Enqueue (f x) $ fmap f xs

instance Foldable DQueue
  where
    foldr = error "not done"

sample1 :: DQueue Int
sample1 =  Enqueue 5 $ Enqueue 7 $ Enqueue 9 Empty

结果应该是这样的:

fmap (+1) sample1 ~?= Enqueue 6 (Enqueue 8 (Enqueue 10 Empty))
foldr (+) 0 sample1 ~?= 24

fmap 似乎在逻辑上是正确的,但我得到一个错误: 函数 fmap

中的非详尽模式

提前致谢。

您的 Functor 实例定义并不详尽,因为它没有处理 DQueue 的所有可能类型构造函数。也就是说,它缺少匹配 Empty 的模式。当您的值为 Empty.

时,您需要定义如何处理 fmap

错误不言自明:您对 Functor 的定义定义为:

data DQueue a = Empty | Enqueue a (DQueue a) deriving (Eq, Show, Read)

instance Functor DQueue where
    fmap f (Enqueue x xs) = Enqueue (f x) $ fmap f xs

然而,有可能(在这种情况下,如果我正确理解你的数据结构,确定性)最终 fmap 将被提供一个 Empty 实例。因此,您必须将定义扩展为:

instance Functor DQueue where
    fmap f (Enqueue x xs) = Enqueue (f x) $ fmap f xs
    fmap _ Empty = Empty

大多数编译器都支持一个标志,这样编译器会抱怨非详尽模式,对于 Glasgow Haskell 编译器 (ghc),您可以使用 -fwarn-incomplete-patterns 标志。例如:

$ ghc queue.hs -fwarn-incomplete-patterns
[1 of 1] Compiling Main             ( queue.hs, queue.o )

queue.hs:7:5: Warning:
    Pattern match(es) are non-exhaustive
    In an equation for ‘fmap’: Patterns not matched: _ Empty
Linking queue ...