所以我输入了
{-# 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.
事情是,m
和m->a
不能相等!为什么它会给我一个冲突? (另外,有关如何制作多变量mconcat的任何提示(采用printf
库的风格)?
答案 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]