2013-03-05 4 views
6

gen :: Int -> [Foo]이라는 소유주 인 Foo 클래스가 있습니다. 이 전 기능 bar :: Bar -> IO()를 정의 Bar라는 또 다른 클래스를 상상하자, 이제클래스를 다른 클래스의 인스턴스로 만들기

data FooTest = FooTest Int 

instance Foo FooTest where 
    gen n = replicate n (FooTest 0) 

: 예를 들어, 나는 Foo의 그런 식으로 인스턴스를 만들 수 있습니다. Foo의 각 인스턴스는 Bar, 이지만Bar 구현은 각 인스턴스에 대해 완전히 동일해야합니다. 다음은 예입니다 :

class Foo f where 
    gen :: Int -> [f] 

class Bar b where 
    bar :: b -> IO() 

instance Bar Foo where -- obviously that doesn’t work 
    bar _ = putStrLn "bar through any Foo instance" 

instance (Foo f) => Bar f where -- this needs the FlexibleInstance GHC extension first, then it still throws shit saying that the constraint is not smaller that I don’t shit 
    bar _ = putStrLn "bar through any Foo instance" 

여기서 문제는 첫 번째 클래스의 인스턴스가 다른 인스턴스화 동일한 구현을 공유 할 수 있다는 사실을 언급 다른 인스턴스를 클래스를 만들 수있는 방법을 찾을 수 없다 수업.

아이디어가 있으십니까?

미리 감사드립니다.

답변

4

두 개의 확장자 (FlexibleInstancesUndecidableInstances)를 사용하여 원하는 것을 정확히 수행 할 수 있습니다.

두 번째 확장명은 이름에서 알 수 있듯이 종료되지 않을 가능성이있는 인스턴스를 작성할 수 있습니다. 이로 인해 컴파일 타임에 무한 루프가 발생할 수 있습니다. 그러나 구현은 특정 재귀 수준에서 임의로 제한되므로 실제로 무한한 컴파일 시간을 가져서는 안됩니다.

확장 기능을 전혀 사용하지 않으면이 작업을 수행 할 수있는 방법이 없습니다. 그러나 장래에 다른 컴파일러를 사용하고 싶지 않으면 확장 기능을 사용하는 것이 본래 나쁘지는 않습니다.

또한 임의의 스타일 메모 : 하나의 제약 조건 만있는 경우 괄호는 선택 사항입니다. 그래서 다음과 같이 작성할 수 있습니다 :

instance Foo f => Bar f where ... 

이것은 매우 중요하지는 않지만 두 번째 버전이 더보기 좋다고 생각합니다.

+0

감사합니다. 필자가 아는 한, FlexibleInstance는 무엇을위한 것인가? 두 개의 확장이 쌍으로 작동합니까? – phaazon

+1

모든 컨텍스트에서 일관되게 괄호를 씁니다. 따라서 형식 시그니처 및 클래스/인스턴스 헤드를보다 쉽게 ​​읽을 수 있습니다. 그래서 나는 당신의 스타일 노트에 동의하지 않습니다. – ertes

+0

FlexibleInstaces 관련 :이 QA도 참조하십시오. http://stackoverflow.com/questions/8367423/are-haskell-flexibleinstances-a-stable-extension-to-the-language – scravy

관련 문제