2013-05-08 4 views
7

나는 다음과 같은 typeclass을 사용하고 있습니다 :하스켈이 두 모듈에서 같은 인스턴스를 가져 오지 않게하는 방법?

module T where 
class T a where 
    v :: a 

내가 구현 T Int의 인스턴스 :

import T 
import A (av) 

instance T Int where 
    v = 0 

main = putStrLn (av ++ show v) 

그리고 나는 또한 인스턴스를 가지고에서 값을 사용하려는 모듈을 T Int.

module A where 
import T 
instance T Int where 
    v = 0 
av = "value from A" 

문제는이 작동하지 않을 수 있습니다 :

$ runghc Main.hs 

Main.hs:4:9: 
    Duplicate instance declarations: 
     instance T Int -- Defined at Main.hs:4:9-13 
     instance T Int -- Defined at A.hs:3:9-13 

하스켈 같은 예를 들어 두 선언이 있다는 것을 뿌려줍니다. B에서 인스턴스를 가져 오지 말라고하거나 두 인스턴스를 통합하거나 Main의 인스턴스 만 사용하려면 어떻게해야합니까?

+1

이렇게하지 마십시오. 적절한 해결책은 인스턴스를 한 곳에서 선언하는 것입니다. – hammar

+0

@hammar :'T' 또는'B'를 쓰지 않았지만'B'의 값을 사용하고 싶습니다.'T'의 인스턴스를 만들고 싶습니다. – Dog

+1

아, 그게 더 까다 롭습니다. 이 경우, 기존 타입을 래핑하는'newtype'을 만들 수 있고 대신에'newtype'을위한 인스턴스를 작성할 수 있습니다. – hammar

답변

8

아쉽게도 인스턴스 가져 오기 및 내보내기 방법을 제어 할 수 없습니다. Do Haskell imports have side effects?을 참조하십시오.

즉, 인스턴스가 하나의 파일에만 정의되도록 코드를 리팩토링해야합니다. 일반적으로 클래스 또는 데이터 유형을 정의하는 파일의 인스턴스 만 정의하는 것이 가장 좋습니다. 실제로이 규칙을 따르지 않는 "고아"인스턴스에 대한 경고도 있습니다. 을 참조하십시오.

그러나 어떤 이유로 든이 작업을 수행 할 수 없으면 파일 중 하나를 선택하여 유지하거나 새 모듈을 만들 수도 있습니다. 해당 특정 인스턴스를 필요로하는 모든 파일에 의해 임포트됩니다. 당신이 두 개의 인스턴스가 같은 다른 일을, 한 가능성에 대처 얼마나 더 일반적으로

:이 두 가지를 명확하게하기 위해 정말 아무 즉시 확실한 방법은 크게 하스켈 방법을 변경하지 않고있다

instance T Int where v = 0 
{- And in a different file: -} 
instance T Int where v = 1 

typeclass 시스템 작동합니다.

인스턴스 중 하나를 직접 작성 했으므로 인스턴스 하나를 제거하기 만하면됩니다. 미리 정의 된 모듈과 동일하기 때문에 모듈을 가져와야합니다.

+0

"이것은 인스턴스가 하나의 파일에서만 정의되도록 코드를 리팩토링해야 함을 의미합니다." 어떻게해야합니까? 나는'T' 또는'B'라고 쓰지 않았습니다. – Dog

+0

오. 그럼, 나쁘다. 이것이 고아 인스턴스를 작성하지 않아야하는 이유입니다. 고아의 인스턴스가있는 모듈, 즉 클래스 또는 유형을 정의하지 않고 인스턴스가있는 모듈로이 문제에 대한 버그를 제기합니다. –

+2

@ Dog : 사실, 당신의 문제를 오해했을 수도 있습니다. 인스턴스 중 하나를 작성 했으므로이를 삭제하십시오. 당신이해야한다면'newtype'을 위해 그것을 씁니다. –