2011-01-06 4 views
7

나는 Haskell의 다항식에 대해 다항식 r과 그것에 대한 Ring 인스턴스를 가지고있다. (class Ring r where plus :: r -> r -> r ; times :: r -> r -> r ; negative :: r -> r ; zero :: r ; one :: r - Num의 단순화 된 버전입니다.) 정의하고 싶지 않은 데이터 타입을 정의하기

는 에이젠슈테인의 정수에 대한 가우스 정수 또는 "다항식 정수/(에이젠슈테인)"를 "다항식 정수/(가우스)"지금은 gauss = x^2 + 1 또는 eisenstein = x^2 + x + 1로 다항식 등을 정의 할 수 있습니다 다음에서 작동합니다. 그것이 문제입니다. 실제 데이터 유형이 아니기 때문에 따옴표로 썼습니다. 정의 방법을 알 수 없습니다.

내가 먼저 data Quotient p = Quot p p 그런 짓을하려하고, 예를 들어 우리는 이미 아주 나쁜이지만이 onezero를 정의도 불가능 물론 plus (Quot a i) (Quot b i') | i == i' = Quot (plus a b) i있을 것입니다. 그래서 data Quotient p = Quot p (Maybe p)으로 바꿨는데 제 생각에는 작동중인 구현을 사용하고 있다고 생각합니다. 그러나 plus이 작동하는지 (적어도 하나의 Just이 필요하고 두 개가 같아야합니다) 확실히 알 수는 없습니다.

안전하지 않은 함수를 사용하는 것은 안전합니까? iskell에서 이것을 프로그래밍하는 방법이 있습니까? 나는 꽤 난처한 처지이다. 감사!

+0

당신이 정말로 원하는 것은 [의존형] (http://en.wikipedia.org/wiki/Dependent_type) (하스켈에는 존재하지 않음)입니다; 이것은 데이터 타입이 값에 의해 매개 변수 화되는'data Quotient (p :: *) (q :: Polynomial r) = Quot p'와 같은 것을 말할 수있게합니다. 이 경우 에뮬레이션 할 수있는 방법이 있지만 확실하지 않습니다. –

+0

Numeric Prelude (http://hackage.haskell.org/package/numeric-prelude-0.2)를 보셨습니까? 그들은 이런 종류의 문제를 해결하기 위해 많은 노력을 기울였습니다. –

+0

@Antal, 각 다항식에 newtype을 사용하면 'Quotient'가 작동한다고 생각합니다. 그래도 고통스러워. –

답변

1

implicit configurations 용지 (cabalized here)는 Z의 몫을 예로 사용합니다. 다항식 고리에 맞춰야합니다 (뭔가 빠뜨린 것이 아니라면).

편집 : 암시 적 구성 자체는 말하지 않고은 직접적입니다.) - 단지 수정.

5

아마도 인덱스 또는 태그로 다항식 유형을 늘릴 수 있습니까? 만약 내가 제대로 이해하고, 일반 모듈과 같은 것이다 :

data Poly r = Poly r 

class Ring r where 
    plus :: r -> r -> r 
    times :: r -> r -> r 

instance Ring (Poly Integer) where 
    plus (Poly x) (Poly y) = Poly (x + y) 
    times (Poly x) (Poly y) = Poly (x * y) 

gauss :: Poly Integer 
gauss = Poly 1 

eins :: Poly Integer 
eins = Poly 2 

을 그리고 안전하게 반지의 두 "하위 유형"사이에 차동 할 수 있어야합니다. 아마 당신은 그래서 그들에 태그를 수 : 반지의

newtype PolyI i r = PolyI r 

instance Show r => Show (PolyI i r) where 
    show (PolyI p) = show p 

instance Ring (PolyI i Integer) where 
    plus (PolyI x) (PolyI y) = PolyI (x + y) 
    times (PolyI x) (PolyI y) = PolyI (x * y) 

우리의 경우는 지금 우리가 간단없는 생성자 유형을함으로써 만들 수 있습니다 추가 유형 인수 i가 필요합니다.

data Gauss 
data Eins 

그리고 우리는 단지 인수로 인덱스 특정 다항식 생성 : 위의 Show 인스턴스와

gaussI :: PolyI Gauss Integer 
gaussI = PolyI 11 

einsI :: PolyI Eins Integer 
einsI = PolyI 20 

을, 우리 얻을 다음과 같은 출력 :

*Poly> plus einsI einsI 
40 

다음

*Poly> plus einsI gaussI 

Couldn't match expected type `Eins' with actual type `Gauss' 
Expected type: PolyI Eins Integer 
    Actual type: PolyI Gauss Integer 
In the second argument of `plus', namely `gaussI' 

그게 당신이 찾고 있던 것과 같습니까?

편집 : 당신이 다시 구현 Poly Integer 인스턴스의 부담을 완화 NewtypeDeriving를 사용하는 경우 질문에 대한 newtype에 주석 후, 나는이 수도 또한 우아한 해결책을 생각합니다. 나는이 접근법보다 약간 더 우아하다면 결국 비슷할 것이라고 생각한다.

+0

' PolyI'를'data PolyI ir = PolyI r deriving Show'라고 부르며, 형식 시그니처 ('PolyI3 :: PolyI Gauss Integer')를 지정해야하는 대가를 치러야 만합니다. –

+0

아, 맞습니다. 이 상황에서, 아마도 긴 서명을 여러 번 타이핑하지 않아도되는 것을 피하기 위해 (Eins와 마찬가지로) 간단한 함수를 정의 할 수 있습니다 ('polyIGauss :: Integer -> PolyI Gauss Integer'도 마찬가지입니다). – ScottWest

+0

''newtype PolyIr = PolyI''와'gaussI :: PolyI Gauss Integer'는'undefined' 사업을 할 필요가 없습니다. 가우스 = 폴리 11 '. 그런 다음'PolyI' 생성자를 숨 깁니다. – luqui

관련 문제