문제

그래서 나는 함께 많이 사용할 수있는 한 쌍의 타입 클래스가 있으며, 매번 둘 다 지정하지 않기를 원합니다. 기본적으로, 넣는 대신

:: (Ord a, Fractional a, Ord b, Fractional b, ... Ord z, Fractional z) =>

내 모든 유형 사양의 시작 부분에서 오히려

:: (OrdFractional a, OrdFractional b, ... OrdFractional z)

그래서 이것을하는 방법에 대한 나의 초기 아이디어는 새로운 타입 클래스를 선언하는 것이 었습니다.

module Example where

class (Fractional a, Ord a) => OrdFractional a

example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool
example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

그러나 이것은 내가 원했던 것처럼 자동으로 작동하지 않았습니다.

% ghci
Prelude> :l Example.hs
Ok, modules loaded: Example.
Prelude Example> example (1::Float,3::Float) (2,2) (3,1)

<interactive>:1:0:
    No instance for (OrdFractional Float)
      arising from a use of `example' at <interactive>:1:0-39
    Possible fix:
      add an instance declaration for (OrdFractional Float)
    In the expression: example (1 :: Float, 3 :: Float) (2, 2) (3, 1)
    In the definition of `it':
        it = example (1 :: Float, 3 :: Float) (2, 2) (3, 1)

수동으로 인스턴스를 생성하는 것은 드래그처럼 보입니다. 다음에 인스턴스를 자동으로 생성하려고 할 수 있다고 생각했습니다.

module Example where

class OrdFractional a
instance (Fractional a, Ord a) => OrdFractional a

example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool
example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

그러나 컴파일러는 그것을 좋아하지 않았습니다.

ghc -c Example.hs

Example.hs:4:0:
    Illegal instance declaration for `OrdFractional a'
        (All instance types must be of the form (T a1 ... an)
         where a1 ... an are type *variables*,
         and each type variable appears at most once in the instance head.
         Use -XFlexibleInstances if you want to disable this.)
    In the instance declaration for `OrdFractional a'

그래서 내가 할 수있는 방법이 있습니까?

도움이 되었습니까?

해결책

GHC 7.4에 도입 된 제약가 확장으로 제약은 이제 종류의 종류입니다. Constraint, 따라서 일반 유형 동의어를 사용하여 원하는 것을 얻을 수 있습니다.

{-# LANGUAGE ConstraintKinds #-}

type OrdFractional a = (Ord a, Fractional a)

다른 팁

당신이 원하는 것은 클래스 별칭입니다. Haskell에 추가 할 제안이 있습니다. http://repetae.net/recent/out/classalias.html

컴파일러가 말할 때 "Use -XFlexibleInstances", 당신은 추가해야합니다

{-# LANGUAGE FlexibleInstances #-}

소스의 맨 위에 (그리고 물론 그것이 무엇을하는지 배우기 위해 문서를 읽으십시오!).

이 특정 경우 코드가 작동합니다.

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

활성화하려면 유연한 인스턴스가 필요합니다 => 인스턴스 헤드의 컨텍스트 및 부적절한 인스턴스는 컴파일러가 처리 할 때 필요합니다. OrdFractional a 컨텍스트는 추가를 끝낼 수 있습니다 Fractional a 그리고 Ord a 맥락으로 - 마침내 결정하는 데 직접 도움이되지 않습니다. a, 적절하게 끔찍한 상황에서, 타이 테크는 분기 될 수있다. 컴파일러는 실제로 그것을 좋아하지 않습니다. (컴파일러가 영원히 계속되거나 기억이 떨어지면 마음에 들지 않을 것입니다.)

아니.

다른 클래스를 암시하는 슈퍼 클래스 솔루션은 Haskell에서 가능한 것과 가장 가깝습니다. 그것은 새로운 클래스의 수동 인스턴스가 필요하지만 때로는 때때로 사용됩니다. 재 작성 도서관.

Cesarb가 언급 한 바와 같이, 클래스 별명은 당신이 원하는 것을 (그리고 그 이상) 말했지만, 그것들은 지금 몇 년 동안 있었고 구현 된 적이없는 제안 일뿐입니다. 아마도 많은 문제가 있기 때문일 것입니다. 대신, 다양한 다른 제안이 나타 났지만 그 중 어느 것도 시행되지 않았습니다. (해당 제안 목록은 이것을 참조하십시오. Haskellwiki 페이지.) 프로젝트 중 하나 HAC5 호출되는 클래스 별칭의 작은 부분 집합을 포함하도록 GHC를 수정하는 것이 었습니다. 맥락 동의어 (여기서 당신이 여기서 요구하는 일을 정확히하고 더 이상 아무것도하지 않습니다) 슬프게도 결코 끝나지 않았습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top