为什么我会发生冲突?

时间:2016-01-22 03:35:18

标签: haskell ghc typeclass functional-dependencies polyvariadic

所以我输入了

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies #-}

import Data.Monoid

class Monoid m => Mconcat m a | a -> m where
    mcon :: m -> a

instance Monoid m => Mconcat m m where
    mcon m = m

instance Mconcat m a => Mconcat m (m -> a) where
    mcon m m' = mcon (m `mappend` m')

我得到了

[1 of 1] Compiling Main             ( pad.hs, interpreted )

pad.hs:8:10:
    Functional dependencies conflict between instance declarations:
      instance Monoid m => Mconcat m m -- Defined at pad.hs:8:10
      instance Mconcat m a => Mconcat m (m -> a)
        -- Defined at pad.hs:11:10
Failed, modules loaded: none.

事情是,mm->a不能相等!为什么它会给我一个冲突? (另外,有关如何制作多变量mconcat的任何提示(采用printf库的风格)?

1 个答案:

答案 0 :(得分:3)

您可以通过更改第二个实例声明并添加UndecidableInstances来进行编译并执行您想要的操作:

{-# LANGUAGE UndecidableInstances #-} 
...
instance {-# OVERLAPS #-} (Mconcat m a, o ~ (m -> a)) => Mconcat m o where 

或早期版本的GHC应该可以使用(未​​经测试)

{-# LANGUAGE UndecidableInstances, OverlappingInstances #-} 
...
instance (Mconcat m a, o ~ (m -> a)) => Mconcat m o where 

这是有效的,因为GHC仅查看实例的头部以确定它是否满足coverage condition,但您可以(几乎)始终通过进行此转换来实现相同的实例。它甚至可以处理多态案例!

>:set +t
>mcon [1] [2] [34,34,2,53] [34,23,43]
[1,2,34,34,2,53,34,23,43]
it :: Num t => [t]
>mcon "a" "b" "c" "d" "e"
"abcde"
it :: [Char]