1

親愛なる Haskell/GHC 専門家の皆様

提供されたコンテキストに従って実際に有効なのは1つだけなのに、GHCが重複するインスタンスを報告する理由がよくわかりません。たとえば、次のコードを考えてみましょう。

{-# LANGUAGE FlexibleInstances #-}

class C a where
    foo :: a -> String
    foo x = "OK"

instance C Bool
instance (C a) => C [a]
instance (C a) => C [(Char, a)]

main = print $ foo [('a', True)]

それをコンパイルすると、次のようになります。

Test.hs:13:16: error:
    * Overlapping instances for C [(Char, Bool)]
        arising from a use of `foo'
      Matching instances:
        instance C a => C [a] -- Defined at Test.hs:9:10
        instance C a => C [(Char, a)] -- Defined at Test.hs:11:10
    * In the second argument of `($)', namely `foo [('a', True)]'
      In the expression: print $ foo [('a', True)]
      In an equation for `main': main = print $ foo [('a', True)]

ポイントは、のインスタンスではない('a', True)型を持つことです。したがって、値には適用されません。(Char, Bool)Cinstance C a => C [a][('a', True)]

では、なぜGHCはそれを考慮するのでしょうか?

問題は、問題を回避する方法 (例: を使用) ではなく、GHC の動作を理解することOverlappingInstancesです。関数呼び出しを「解決」するときにコンテキストが使用されていないためですか?もしそうなら、なぜですか?

前もって感謝します!

4

1 に答える 1

2

私の理解(非常に間違っている可能性があります):

まず、ドキュメントから:

マッチングの際、GHC はインスタンス宣言のコンテキスト (context1 など) を考慮しません。GHC のデフォルトの動作は、解決しようとしている制約に正確に 1 つのインスタンスが一致しなければならないというものです。オーバーラップの可能性があっても問題ありません (宣言 (A) と (B) の両方を含めるなど)。エラーは、特定の制約が複数に一致する場合にのみ報告されます。

-XOverlappingInstances フラグは、最も具体的なインスタンスがあれば、複数のインスタンスの一致を許可するよう GHC に指示します。

あなたの場合、渡されるタイプfooはです[(Char,Bool)][a]これは、一般的なものとより専門的なものを満たし[(Char,a)]ます。フラグがないOverlappingInstances場合、最も具体的な一致シナリオは適用されず、エラーが報告されます。

コードを次のように微調整するとします。

instance C Bool
instance (C a) => C [a]
instance (C a) => C (Char, a)

タプルはリストではないため、重複はありません。

于 2017-01-06T10:36:10.717 に答える