2017-01-06 5 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는 왜 그것을 고려합니까?

문제는 실제로 문제를 피하는 방법 (예 : OverlappingInstances 사용)이 아니라 GHC의 행동을 이해하는 것입니다. 함수 호출을 "해석"할 때 컨텍스트가 사용되지 않기 때문입니까? 그렇다면 왜?

미리 감사드립니다.

답변

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

감사합니다. 슈리. 그래서 기본적으로 이것은 (비표준) 확장에서 "GHC가 작동하는 방식"처럼 보입니다. 나는 그 질문을 닫는다. –