2012-08-15 2 views
1

나는이 데이터 Functor의 인스턴스 입력 만들려고 노력 해요 :이 데이터 형식의 Functor 인스턴스를 만들 수 있습니까?

data Fraction = Frac Integer Integer deriving Show 

을하지만, 이런 식으로 정의가 작동하지 않습니다

instance Functor Fraction where 
    pure = Frac 1 1 
    fmap f (Frac a b) = Frac (f a) (f b) 

나는이 기능을 원하는 , 나는 것 Functor의 인스턴스가되도록 데이터를 선호하십시오. 하지만 Fraction의 매개 변수는 항상 두 개의 Integers이므로 일부 법률을 위반합니까?

나는 항상 을 작성하고 Functor 선언을 피할 수 있지만 언어에 익숙해 지려고 노력하고 있습니다. 도움을 주시면 감사하겠습니다!

답변

8

예, 선언을 위해 "제외"할 유형 변수가 없으면 펑터를 정의 할 수 없습니다 (정식 적으로 : 펑터 인스턴스는 종류가 * -> *이어야 함). fmap의 서명은 fmap :: (a -> b) -> f a -> f b이므로 해당 계약을 충족하려면 함수에 대해 ab 유형을 선택해야합니다.

당신은 물론 단지이 될 Fraction을 다시 정의 할 수 있습니다 :

data Fraction a = Frac a a deriving Show 

... 또는 당신은 아무도 때문에 펑을 형성하지 않는, Data.Ratio에 분수/유리수에 대한 기존의 데이터 유형을 사용할 수 있습니다 그러한 인스턴스를 갖는 것이 유용하다고 여겼지 만 (어쨌든 그것을 위해 무엇을 사용하겠습니까?), 적어도 당신은 잘 정립 된 기존의 데이터 구조를 사용하게 될 것입니다.

+0

저는 일종의 운동을위한 작은 도서관을 짓고 있습니다. 'fmap'은 실제로 전혀 유용하지 않을 수도 있습니다 ... 나는 그것이 좋은 지적이라고 생각합니다. 하지만 어쨌든, 설명해 주셔서 감사합니다! 그게 나를 도와 줘. –

+1

'fmap'에 대한 유일한 사용법은 분자와 분모를 일반적인 값으로 나누는 데 사용할 수 있다는 것입니다. 패턴 매칭. 또한 무언가가 잘못되었다는 가장 큰 신호는 '정수'만 사용하도록 제약을 받더라도 '분수'에 '순수'를 ​​구현하는 합리적인 방법이 없다는 것입니다. 왜 '1/1' 번호가 특별합니까? '0/12' 또는'42/1'을 사용하지 않는 이유는 무엇입니까? 그러나 당신은'Monoid' 타입 클래스와 ['algebra'] (http://hackage.haskell.org/package/algebra) 패키지의 다양한 클래스에 관심이있을 것입니다. – dflemstr

+0

(대수학 패키지의 경우, 최신 버전이 어떻게 든 고장 나고 문서가 없기 때문에 이전 버전을 클릭해야 할 수도 있습니다.) – dflemstr