2017-01-06 2 views
1

親愛なるハスケル/ GHCの専門家単一のものを可能にしながら、報告の重複の場合、ハスケル/ GHC:コンテキストのみ

一方のみを提供し、コンテキストに従って、実際に有効である一方、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)Cのインスタンスではありませんどの(Char, Bool)を入力していることです。したがって、[('a', True)]にはinstance C a => C [a]が適用されません。

したがって、なぜGHCはそれを考慮しますか?

問題は実際にGHCの動作を理解することであり、問​​題を回避する方法(例:OverlappingInstancesを使用)ではありません。なぜなら、コンテキストコールは関数呼び出しを "解決"するときに使用されないからですか?もしそうなら、なぜですか?

ありがとうございます!

答えて

2

私の理解で(非常に間違っている可能性):

まず、documentationから:

一致するとき、GHCがインスタンス 宣言(CONTEXT1など)の状況を考慮していません。 GHCのデフォルトの動作は、正確に のインスタンスが解決しようとしている制約と一致しなければならないということです。 (宣言(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) 

タプルがリストではありませんので、その後、重複はないだろう。

+0

ありがとうShree。だから、基本的には、この(非標準的な)拡張では単に「GHCの仕組み」のように見えます。私はその質問を閉じます。 –