2016-01-22 124 views
0

所以我打这件事为什么我会发生冲突?

{-# 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不能相同!为什么它给我一个冲突? ?(而且,任何秘诀,如何让一个polyvariadic mconcat(在printf库的风格)

+2

在第一个实例中用'm'替代'm'。 –

+0

@ReidBarton哦,杜。出于某种原因,我认为这不会打破它。 – PyRulez

+0

如果您将第二个实例更改为'instance(Mconcat ma,o〜(m - >),那么您可以进行编译,并且可能做你想做的事情(尽管我不确定那是什么,所以我不太确定) a))=> Mconcat mo' - 这需要'UndecidableInstances'。在第二个实例中用于更高版本的'OverlappingInstances'或'OVERLAPS'编译指示。 – user2407038

回答

2

您可以将此编译和你想要做什么改变二审声明并添加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,但你可以(Almos酒店t)通过进行这种转换总是获得相同的实例。它甚至可以处理多态的情况!

>: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] 
+0

我敢打赌,这会对html库有一个很好的补充(所以你不必滥用'do'符号)。 – PyRulez

+0

类型推断通常会与可变参数函数进行相当大的斗争,这经常会使它们在实践中不够用。在这种情况下,我感到很惊讶。它可能是新的'OverlappingInstances'机制,但是我不太了解它,所以我不知道。 – user2407038

相关问题