2015-01-07 7 views
6

EitherMaybe에 대한 문서는 해당 인스턴스가 Show임을 나타냅니다.왜 둘 중 하나가 표시를 가져 오지만 어쩌면 그렇지 않을까요?

Either 단순히 Show을, 파생 다음과 같이 정의된다

data Either a b = Left a | Right b 
    deriving (Eq, Ord, Read, Show, Typeable) 

그러나, Maybe하지 않습니다 : 그들은 base의 일부이며 매우 비슷하기 때문에

data Maybe a = Nothing | Just a 
    deriving (Eq, Ord) 

이유 Maybe 직접 유도하지 않습니다 Show?

또 다른 질문으로는 Show 인스턴스가 있습니까?

답변

10

Maybe의 인스턴스는 튜플과 같은 다른 일반적인 유형의 인스턴스와 함께 GHC.Show에 명시 적으로 정의됩니다. ,

Prelude> :i Maybe 
data Maybe a = Nothing | Just a  -- Defined in ‘Data.Maybe’ 
instance Eq a => Eq (Maybe a) -- Defined in ‘Data.Maybe’ 
instance Monad Maybe -- Defined in ‘Data.Maybe’ 
instance Functor Maybe -- Defined in ‘Data.Maybe’ 
instance Ord a => Ord (Maybe a) -- Defined in ‘Data.Maybe’ 
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’ 
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’ 

나는 그들이 인스턴스를 명시 적으로 정의 된 이유를 알고 또는 내가 말할 수있는 지금까지 GHC.Show 대신 Data.Maybe의 -as에 넣어하지 않습니다 : 인스턴스가 ghci:i 명령을 사용하여 정의 된 어디 있는지 알 수 있습니다 Data.Maybe으로 이동하거나 파생 될 수 있습니다. 내 생각 엔 Data.MaybeGHC.Base (지금처럼) 이외의 다른 것에 의존하지 않기를 바랄 것입니다. 아마도 다른 코어 모듈 중 일부에서 사용 되었기 때문일 것입니다.

4

AFAIK 튜플은 어디에도 정의되어 있지 않으므로 [1] 복제본의 Show 인스턴스가 GHC.Show [2]에 정의되어야합니다. 해당 인스턴스의 구현은 foldr1를 사용하는 일 :

show_tuple :: [ShowS] -> ShowS 
show_tuple ss = showChar '(' 
       . foldr1 (\s r -> s . showChar ',' . r) ss 
       . showChar ')' 

그래서 GHC.Show 그 함수가 정의 GHC.List를 가져옵니다. GHC.List는 Maybe 모나드 (좋은 오래된 Haskell 98의 단동 변이 편견에 속하는)에있는 lookup을 정의합니다. GHC.List가 Data를 가져옵니다. 아마도. Show 인스턴스를 정의하려면 Data.Maybe가 전체 시퀀스 GHC.Show (직접 또는 간접적으로)를 가져와야합니다. GHC.Show -> GHC.List -> Data.Maybe -> GHC.Show circular 의존. GHC는 순환 의존성을 매우 잘 지원하지 않습니다 (지원하기 쉽지는 않습니다!). 그래서 기초는 그들을 피하기 위해 정말로 힘듭니다.

[1] 고아 인스턴스는 인스턴스와 관련된 클래스 및 유형과 다른 모듈에 정의 된 인스턴스입니다. 공식적으로, 하스켈은 컴파일되는 모듈에 의해 직접 또는 간접적으로 임포트 된 모듈에서 인스턴스 검색을 수행해야합니다. 하지만 고아가 아닌 경우 GHC는이를 단락시키고 두 곳을 살펴볼 수 있습니다. 고아 인스턴스의 경우 모듈의 모든 고아 인스턴스를 추적 한 다음 해당 인스턴스를 가져 오는 모든 모듈에서 해당 인스턴스가 다시 노출된다는 것을 추적해야합니다.이 인스턴스는 비용이 많이 들며 (잠재적으로 인스턴스가 많은 상황 환경을 유지해야 함을 의미합니다. 현재 클래스 나 유형을 가져 오지 않기 때문에 현재 모듈과 관련이 없습니다. 따라서 좋은 사례는 그 이유 때문에 인스턴스가 고아가되는 것을 방지하는 것입니다.

다소 더 철학적으로, 고아 인스턴스는 프로그램에서 동일한 클래스/유형의 충돌하는 두 인스턴스를 얻는 매우 좋은 방법입니다.이 두 인스턴스는 모두 사용자의 Main 모듈에서 '가시적'이므로 충돌합니다. 그래서 언어 기능 자체가 일종의 사기성입니다.

[2] IIRC GHC는 매우 하스켈 (98)을 준수 가 아니라 어떤 실제적인 프로그래밍의 필요성에 대한 충분 튜플 구성 요소의 (상대적으로 작은) 고정 된 수에 Show 인스턴스를 제공한다. (진심으로, 3 개 이상의 요소가있는 튜플을 사용하지 마십시오. 은 특정 구성 요소의 의미를 잊어 버릴 것입니다. 지난 몇 년간 GHC를 준수하도록 표준이 업데이트되었는지는 모르겠습니다.