Haskell fmap仿函数

时间:2016-06-23 09:42:01

标签: haskell functor algebraic-data-types

基于指定的代数数据结构,我遇到了基于队列的仿函数问题。

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中的非详尽模式

提前谢谢。

2 个答案:

答案 0 :(得分:6)

您的Functor实例定义并非详尽无遗,因为它不处理DQueue的所有可能的类型构造函数。也就是说,缺少匹配Empty的模式。当值为fmap时,您需要定义如何处理Empty

答案 1 :(得分:4)

错误不言而喻:您对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 ...