2012-06-22 4 views
18

GHC에는 DeriveFunctor, DeriveDataTypeable 등과 같은 몇 가지 언어 플래그가있어 Haskell 98에서 허용되는 유형 클래스 이외의 유형 클래스에 대해 파생 인스턴스를 컴파일러에서 생성 할 수 있습니다. 이는 특히 Functor과 같은 유형에 대해 명백한 "자연"파생 인스턴스를 지시합니다.왜 GHC가 Monoid에 대한 인스턴스를 생성 할 수 없습니까?

그럼 Monoid을 사용하지 않으시겠습니까? (의사 코드를 변명)

data T = MkT a b c ... 

하나가 기계적으로 Monoid 인스턴스를 생성 할 수 있습니다 : 그것은 하나의 데이터 생성자 모든 데이터 유형에 대한 것 같아

instance (Monoid a, Monoid b, Monoid c, ...) => Monoid T where 
    mempty = 
    MkT mempty mempty mempty ... 
    mappend (MkT a1 b1 c1 ...) (MkT a2 b2 c2 ...) = 
    MkT (mappend a1 a2) (mappend b1 b2) (mappend c1 c2) ... 

내가 알고 있어요 그 derive 패키지 provides this, 하지만 제 질문은 GHC가 왜 그런지에 대한 질문입니다.

+0

@sdcvvc : 이것은 질문에 대한 유효한 대답 인 것 같습니다. 아마도 당신은 그것을 게시해야합니까? –

+0

좋아, 대답했다. – sdcvvc

+1

일반적으로 'Functor'인스턴스를 만드는 유일한 방법이 있습니다. '모노 이드 '에 대해서도 마찬가지입니다. – augustss

답변

14

실제로는 Monoid을 유도 할 수 없다는 임의적 결정이지만, 모노도 역시 매우 일반적이어서 유형을 모노로이드 (monoid)로 만드는 많은 방법이 있습니다. 다음 예를

data T = A | B | C deriving (Eq, Ord, Enum) 

type Mon a = (a, a -> a -> a) 

m1, m2, m3, m4 :: Mon T 
m1 = (A, max) 
m2 = (C, min) 
m3 = (A, \ x y -> toEnum $ (fromEnum x + fromEnum y) `rem` 3) 
m4 = (B, f4) 
f4 A _ = A 
f4 B x = x 
f4 C _ = C 

이 (장치 이진 연산을 포함하여 Mon) T 모노 이드 있도록 네 개의 합리적인 방법을 도시한다. 첫 번째는 최대 값을 취하는 모노 노이드이며, 두 번째는 최소값을 취하고 세 번째는 모듈로 3 산술에서 모노 노이드이며, 네 번째는 Ordering 유형에 사용되는 모노 노이드입니다. 정말 자연적인 방법으로 두드러지지 않습니다.

7

Num과 다른 클래스에 대해서도 같은 질문을 할 수 있습니다. 다른 모든 표준 파생어는 여러 생성자가있는 데이터 유형에서 작동합니다.

대신 newtype derived newtype T = MkT (a,b,c) deriving Monoid을 사용할 수 있습니다.

비슷한 확장자 : 빈 데이터 유형을 거의 모든 유형 클래스의 인스턴스로 만들 수 있습니다.

deriving 절은 사전 정의 된 클래스에서만 작동하기 때문에 항상 하스켈의 특수하고 불편한 부분이었습니다. 애드혹 확장을 추가하면 언어가 복잡해집니다. 대신, GHC는 최근에 generic deriving에 대한 지원을 받았습니다.

+1

글쎄, '파생'과 같은 임시 방편이있을 수 있으므로, 그들은 그 힘을 계속 확장 해 왔습니다. 다시 말하지만, '모노 이드'를 유도하는 다른 메커니즘이 있다는 것을 알고 있습니다. 대신 왜 DeriveFunctor (및 기타)가 존재하는지, DeriveMonoid (및 기타)는 왜 존재하지 않는지 구체적으로 묻고 있습니다. 그냥 독단적입니까? – mergeconflict

+2

결국 그것은 임의적이지만 제안 된 확장 기능은별로 유용하지 않은 것 같습니다. 대부분의 펑터를 지원하는 특수 언어 기능이 나에게 좋을 것 같습니다. 제품 모노 노드를 제공하는 특수 언어 기능이 추가 보증을하는 것으로 보이지 않습니다. 범위에 대해서 생각해 볼 필요가있다. (만약 '모노 이드'가 다른 클래스라면?). 유용한 모노도 드는 어쨌든 newtype 랩퍼를 사용합니다. 그래서 당신은't = T (Sum Integer) (Endo Char)'라는 파생 형식을 사용하기에 적합합니다. 이것은 중첩 된 생성자와 일치해야합니다. – sdcvvc

+2

합계 유형 인 유용한 모노도가 많이 있지만이 구현은 해당 인스턴스를 파생시킬 수 없습니다.= ( –