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.

しかし、それは同じではmありm->aません。なぜそれは私に対立を与えているのですか? (また、(ライブラリのスタイルで)多変量の mconcat を作成する方法に関するヒントはありprintfますか?

4

1 に答える 1

3

これをコンパイルして、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 がインスタンスの先頭だけを調べてカバレッジ条件を満たすかどうかを判断するためですが、この変換を行うことで (ほぼ) 常に同じインスタンスを実現できます。ポリモーフィックなケースも処理します!

>: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]
于 2016-01-22T04:17:11.990 に答える