2011-01-27 5 views
6

호환되지 않는 데이터 유형을 여러 개 만들고 싶습니다. 즉, 나는 파라미터 화 된 형태 Foo a이, 그리고 실제로 a가 무엇인지에 대해을 돌보는이없는 기능 같은하스켈에서 싱글 톤 유형을 올바르게 생각하고 사용하고 있습니까?

bar :: (Foo a) -> (Foo a) -> (Foo a) 

것입니다. 대한 IntChar (나는 단지 그들이 동일하지 않은 것을 신경)을 동시에 정말 상관 없어 동안 더 명확히하기 위해, 나는

x :: Foo Int 
y :: Foo Char 
bar x y 

일에서 저를 중지 타입 시스템을 싶습니다 .

내 실제 코드에는 주어진 반지를 통해 다항식 형식이 있습니다. 타입 시스템이 s의 다항식을 사용하여 t의 다항식을 더할 수없는 한, 나는 불확정성이 무엇인지 상관하지 않습니다. 내가 치료를 할 때문에 주어진 다항식이 끝난 특정하는 링에 대해 지금까지 내가 typeclass Indeterminate을 만들고,

data (Ring a, Indeterminate b) => Polynomial a b 

이 방식으로 내 다항식 유형을 매개 변수화하여이 문제를 해결했습니다는 Ring 부분을 완벽하게 자연의 느낌 . 아래에 설명 된대로 Indeterminate 부분에 대해서는 매우 고심했습니다.

위의 접근 방식은 정상적으로 작동하지만 인위적으로 느껴집니다. 특히이 부분은 다음과 같습니다.

class Indeterminate a where 
    indeterminate :: a 

data T = T 

instance Indeterminate T where 
    indeterminate = T 

data S = S 

instance Indeterminate S where 
    indeterminate = S 

(기타 등등) 이상하고 잘못 느껴집니다. 본질적으로 Indeterminate의 인스턴스가 싱글 톤이되도록 요청하려고합니다 (this sense). 이상하게 느껴질 수있는 하나의 지표입니다. 또 다른 사실은 실제 b이 종종 유추 될 수 없기 때문에 (실제로 이상하지는 않지만 짜증나지만) 내 Polynomial a b에 많은 주석을 달아야한다는 것입니다.

제안 사항? 나는 이것을 계속해야 할까? 아니면 내가 놓친 것일까?

추신 : 나는 즉시 응답을 upvote하지 않거나 수락하지 않으면 기분을 상하게하지 마십시오. 나는 며칠 동안 다시 체크인 할 수 없을 것이다. 모든

+0

다항식을 반지의 요소 시퀀스 또는 비슷한 것으로 모델링하지 않는 좋은 이유가 있습니까? 예를 들어 부분합 시퀀스? –

+0

자, 여기 조금 잃어 버렸어. 나는 왜 당신이'불확정 '을 필요로하는지 이해하지 못한다. 두 개의 b가 동일하다는 것을 강요하고 싶다면 형식 서명에 그대로 두십시오. – sclv

+0

@ Alexandre C .: 나는 그렇게하고있다. 그러나 타입 시그니처를 "6 +"에 "2 + 5t"를 추가하는 것이 의미없는 것으로 만들고 싶습니다. 반지 요소의 시퀀스로서 다항식을 사용할 때, 타입 시스템 (정당하게)은 다른 링에 계수가있는 반지름의 계수가있는 다항식을 추가하지 못하도록합니다. 그러나 불확정성을 구별하지는 않습니다. 이제, 내가 정말로 불확정성을 필요로하는지 여부는 매우 유효한 질문입니다 :-) – gspr

답변

7

먼저,이 확실하지 않다 :

data (Ring a, Indeterminate b) => Polynomial a b 

... 당신이 그것을 기대하고있다. data의 컨텍스트는별로 유용하지 않습니다. 이유에 대해서는 the discussion here을 참조하십시오. 그 중 대부분은 실제로 많은 추가 유형 보증을 제공하지 않고도 추가 주석을 추가하도록합니다.

둘째, 유형이 고유하게 유지되는지 확인하는 것 이외의 "불확정성"매개 변수에 대해 실제로 신경 씁니까? 그런 종류의 일을하는 꽤 표준적인 방법은 phantom types입니다. - 사실상, 데이터 생성자에서 사용되지 않는 유형 생성자의 매개 변수입니다.

data Foo a b = Foo b 

foo :: Foo a b -> Foo a b 
foo (Foo x) = Foo x 

bar :: Foo a c -> Foo b c 
bar (Foo x) = Foo x 

baz :: Foo Int Int -> Foo Char Int -> Foo() Int 
baz (Foo x) (Foo y) = Foo $ x + y 

는 분명이 있지만 당신이 의도적으로 제한을 추가하는 장소에서, 주석을 필요로 않습니다 함수를 사용하면 원하는만큼 다형성이 될 수 있도록, 예를 들어, 사용하거나 팬텀 형식의 값이 필요 없을거야 .그렇지 않으면 유추가 유령 유형 매개 변수에 대해 정상적으로 작동합니다.

여기서는 여러분이하는 일에 대해 위의 방법으로 충분하다고 생각합니다. 싱글 톤 유형의 비즈니스는 대부분 더 복잡한 유형 수준의 항목과 일반적인 값 수준의 계산 사이의 차이를 값에 대한 프록시를 입력하십시오. 이것은 말하자면, 기초를 나타내는 유형으로 벡터를 표시하거나 물리적 단위로 숫자 값을 표시하는 데 유용 할 수 있습니다. 주석이 "불명확 한 X라는 것"보다 더 의미가있는 경우도 마찬가지입니다.

+1

'-XEmptyDataDecls'를 사용하면 "마커"유형에 런타임 표현이 전혀 없도록 할 수 있습니다 (예 : 'data T' 그리고 개행과 코드를 작성하십시오. 이것은'T'가 생성자가없는 유형이므로 실제로는 형식 시스템에 대한 의미 만 있습니다. – luqui

+0

감사합니다. 나는 네가 내가 묻고 궁금해하는 것을 정확히 가지고 있다고 생각한다. 나는 팬텀 타입에 대해 몰랐다. 그래서 나를 가르쳐 주셔서 감사한다. 싱글 톤이 실제로 사용되는시기에 대한 명확한 설명은 또한 매우 계몽적이며, 문제가있는 핵심 부분으로 이동합니다. (정말로, 내 마음을 읽었습니까?) (참고로, 나는 데이터 정의에 관한 문맥이 유용하지 않다는 것을 안다 - 나는 코드를 작성하는 동안 내 생각을 돕기 위해 사용하지만, 나중에 그것을 제거한다. 나는 묻기 전에 그것을 제거해야한다). – gspr

+1

@gspr : GADT 및 관련 언어 확장에 대해 읽고 싶을 수도 있습니다. 제공하는 표현력이 유용 할 수있는 것처럼 보이기 때문에 실제로 의미있는 데이터 정의의 컨텍스트가 허용됩니다. –