수색…


소개

하스켈의 유형 표시는 해당 유형의 정의와 별도로 유형과 연관된 비헤이비어를 정의하는 수단입니다. 말하자면, 자바에서는 타입 정의의 일부로 동작을 정의하는 반면, 하스켈은이 두 가지를 분리 된 상태로 유지합니다.

Haskell의 base 패키지에 이미 정의 된 여러 가지 유형이 있습니다. 이들 사이의 관계는 아래 비고 섹션에 설명되어 있습니다.

비고

Typeclassopedia 기사에서 가져온 다음 다이어그램은 하스켈의 다양한 유형 간 관계를 보여줍니다.

typeclassopedia에 게시 된 그림 1의 표준 하스켈 유형 클래스 간의 관계.

어쩌면 펑터 클래스

Haskell에서 데이터 타입은 함수처럼 인자를 가질 수있다. Maybe 유형을 예로 들어 보겠습니다.

Maybe 실패 나 그 가능성에 대한 생각을 표현할 수있는 매우 유용한 유형 일 것입니다. 즉, 계산이 실패 할 가능성이있는 경우 Maybe 형식을 사용합니다. Maybe 다른 유형의 래퍼처럼 작동하여 추가 기능을 제공 할 수 있습니다.

실제 선언은 매우 간단합니다.

Maybe a = Just a | Nothing

이것이 의미하는 바는 Maybe 는 성공을 나타내는 Just 와 실패를 나타내는 Nothing 두 가지 형태로 제공된다는 것입니다. Just 의 유형을 결정 하나 개의 인수 소요 Maybe 하고, Nothing 없음을지지 않습니다. 예를 들어 Just "foo" 값에는 Maybe String 유형이 있습니다.이 유형은 Maybe 기능이 추가 된 문자열 유형입니다. 값 Nothing 입력이없는 Maybe a 여기서 a 어떤 유형이 될 수 있습니다.

추가 기능을 제공하기 위해 유형을 래핑하는이 아이디어는 매우 유용하며 단순한 Maybe 이상에 적용 할 수 있습니다. 다른 예로는 서로 다른 기능을 제공하는 Either , IO 및 List 유형이 있습니다. 그러나 이러한 모든 래퍼 유형에 공통적 인 몇 가지 작업과 기능이 있습니다. 가장 주목할만한 것은 캡슐화 된 값을 수정할 수있는 기능입니다.

이러한 종류의 유형을 값을 가질 수있는 상자로 생각하는 것이 일반적입니다. 서로 다른 상자는 다른 값을 가지며 다른 일을하지만, 그 안에있는 내용에 액세스 할 수 없으면 아무 것도 유용하지 않습니다.

이 아이디어를 캡슐화하기 위해 Haskell에는 Functor 라는 표준 typeclass가 있습니다. 그것은 다음과 같이 정의됩니다.

class Functor f where
  fmap :: (a -> b) -> f a -> f b

알 수 fmap 클래스에는 두 개의 인수로 이루어진 단일 함수 fmap 있습니다. 첫 번째 인수는, 한 유형에서 다른 함수 , 서로, a b . 두 번째 인수는 입력 값 함유하는 펑 (래퍼 형)이다 a . b 유형의 값을 포함하는 펑터 (랩퍼 유형)를 리턴합니다.

간단히 말해서, fmap 은 함수를 취해서 functor 내부의 값에 적용됩니다. Functor 클래스의 멤버가 될 수있는 유일한 유형의 함수이지만, 매우 유용합니다. 보다 구체적인 응용 프로그램이있는 펑터에서 작동하는 함수는 ApplicativeMonad 에서 찾을 수 있습니다.

Type 클래스 상속 : Ord 타입 클래스

Haskell은 클래스 확장 개념을 지원한다. 예를 들어, Ord 클래스는 Eq 모든 연산을 상속하지만 값 사이에 Ordering 을 반환하는 compare 함수도 있습니다. Ord 는 공통 순서 비교 연산자와 min 메소드 및 max 메소드를 포함 할 수도 있습니다.

=> 표기법은 함수 서명에서와 동일한 의미를 가지며 Ord 를 구현하기 위해 Eq 를 구현하기 위해 유형 a 가 필요합니다.

data Ordering = EQ | LT | GT

class Eq a => Ord a where
    compare :: Ord a => a -> a -> Ordering
    (<)     :: Ord a => a -> a -> Bool
    (<=)    :: Ord a => a -> a -> Bool
    (>)     :: Ord a => a -> a -> Bool
    (>=)    :: Ord a => a -> a -> Bool
    min     :: Ord a => a -> a -> a
    max     :: Ord a => a -> a -> a

compare 다음의 모든 메소드는 여러 가지 방법으로 파생 될 수 있습니다.

x < y   = compare x y == LT
x <= y  = x < y || x == y -- Note the use of (==) inherited from Eq
x > y   = not (x <= y)
x >= y  = not (x < y)

min x y = case compare x y of
               EQ -> x
               LT -> x
               GT -> y

max x y = case compare x y of
               EQ -> x
               LT -> y
               GT -> x

자체적으로 확장하는 타입 클래스 Ord 는 적어도 compare 메소드 또는 (<=) 메소드 자체를 구현해야하며, 이는 상속 된 상속 격자를 빌드합니다.

Eq

Prelude의 함수와 IO 제외한 모든 기본 데이터 유형 ( Int , String , Eq a => [a] )은 Eq . 유형이 Eq 인스턴스화하는 경우 또는 구조적 동일성에 대해 두 값을 비교하는 방법을 알고 있음을 의미합니다.

> 3 == 2 
False
> 3 == 3
True

필수 메소드

  • (==) :: Eq a => a -> a -> Boolean 또는 (/=) :: Eq a => a -> a -> Boolean (하나만 구현하면 다른 기본값은 정의 된 것)

정의

  • (==) :: Eq a => a -> a -> Boolean
  • (/=) :: Eq a => a -> a -> Boolean

직접 슈퍼 클래스

없음

주목할만한 하위 클래스

Ord

인스턴스 생성 유형 Ord 에는 Int , String[a] (예 : Ord 인스턴스 a 있는 유형 Ord a 경우)가 포함됩니다. 형식이 Ord 인스턴스화하는 경우 해당 유형의 값의 "자연스러운"정렬을 의미합니다. 참고로, 종종 유형의 "자연적인"순서에 대한 가능한 많은 선택이 있으며 Ord 는 우리에게 하나를 선호하도록 강요합니다.

Ord 는 표준 (<=) , (<) , (>) , (>=) 연산자를 제공하지만 사용자 정의 대수 데이터 형식을 사용하여 모두 흥미롭게 정의합니다

data Ordering = LT | EQ | GT

compare :: Ord a => a -> a -> Ordering

필수 메소드

  • compare :: Ord a => a -> a -> Ordering 또는 (<=) :: Ord a => a -> a -> Boolean (표준의 기본 compare 메소드는 구현시 (<=) )

정의

  • compare :: Ord a => a -> a -> Ordering
  • (<=) :: Ord a => a -> a -> Boolean
  • (<) :: Ord a => a -> a -> Boolean
  • (>=) :: Ord a => a -> a -> Boolean
  • (>) :: Ord a => a -> a -> Boolean
  • min :: Ord a => a -> a -> a
  • max :: Ord a => a -> a -> a

직접 슈퍼 클래스

모노 노이드

MonoidMonoid 반환 값을 포함한 목록, 숫자 및 함수를 포함합니다. 인스턴스화 Monoid 연관 이진 동작 지원해야 타입 ( mappend 또는 (<>) )의 값을 결합하고, 특별한 "제로"값 (갖는 mempty )와 같은 그것의 값을 조합하여, 그 값을 변경하지 않는 것을 :

mempty  <>  x == x
x <>  mempty  == x

x <> (y <> z) == (x <> y) <> z

직관적으로 Monoid 유형은 값을 함께 추가 할 수 있다는 점에서 "목록과 유사"합니다. 또는 Monoid 유형은 순서에 대해 신경을 쓰지만 그룹에는 신경 쓰지 않는 값의 연속으로 생각할 수 있습니다. 예를 들어, 이진 트리는 Monoid 이지만 Monoid 연산을 사용하면 분기 구조를 볼 수없고 값의 순회 만 볼 수 있습니다 ( FoldableTraversable 참조).

필수 메소드

  • mempty :: Monoid m => m
  • mappend :: Monoid m => m -> m -> m

직접 슈퍼 클래스

없음

숫자

숫자 유형에 대한 가장 일반적인 클래스입니다. 즉, 반지 에 대해 더 정확하게 말하면, 보통의 의미로 덧셈 및 뺄셈을 할 수 있지만 반드시 나눌 수는 없습니다.

이 클래스에는 Integer 형 ( Int , Integer , Word32 등)과 소수 형 ( Double , Rational , 복소수 등)이 모두 포함됩니다. 유한 타입의 경우, 의미론은 일반적으로 모듈러 산술 , 즉 오버 플로우 및 언더 플로우 로 이해됩니다.

수치 클래스에 대한 규칙은 모나드 또는 모노로이드 법칙이나 평등 비교법 보다 훨씬 엄격하게 적용됩니다. 특히 부동 소수점 숫자는 일반적으로 대략적인 의미로만 법칙을 준수합니다.

방법

  • fromInteger :: Num a => Integer -> a . 정수를 일반 숫자 형식으로 변환합니다 (필요한 경우 범위를 둘러 쌉니다). Haskell 숫자 리터럴 은 주위의 일반적인 변환과 함께 단일 Integer 리터럴로 이해할 수 있으므로 Int 문맥과 Complex Double 설정에서 리터럴 5 를 사용할 수 있습니다.

  • (+) :: Num a => a -> a -> a . 표준 추가, 일반적으로 associative 및 commutative로 이해, 즉,

      a + (b + c) ≡ (a + b) + c
      a + b ≡ b + a
    
  • (-) :: Num a => a -> a -> a . 빼기 (덧셈의 역함수) :

      (a - b) + b ≡ (a + b) - b ≡ a
    
  • (*) :: Num a => a -> a -> a . 곱셈 (multiplication), 덧셈을 통해 분포되는 연관 연산 :

      a * (b * c) ≡ (a * b) * c
      a * (b + c) ≡ a * b + a * c
    

    가장 일반적인 인스턴스의 경우 곱셈도 교환 가능하지만 이것은 필수 조건은 아닙니다.

  • negate :: Num a => a -> a . 단항 부정 연산자의 전체 이름입니다. -1negate 1 문법적 설탕입니다.

      -a ≡ negate a ≡ 0 - a
    
  • abs :: Num a => a -> a . 절대 값 함수는 항상 동일한 크기의 음이 아닌 결과를 제공합니다.

      abs (-a) ≡ abs a
      abs (abs a) ≡ abs a
    

    abs a ≡ 0 경우에만 발생한다 a ≡ 0 .

    실제 유형의 경우 음수가 아닌 의미는 분명합니다. 항상 abs a >= 0 입니다. 복합 등 유형 그러나 결과, 잘 정의 된 순서가없는 abs 항상 (즉,도 부정하지 않고 문자 그대로 하나의 숫자로 기록 될 수있는 번호를 알려) 실제 부분 집합 ‡에서 거짓말을한다.

  • signum :: Num a => a -> a . sign 함수는 이름에 따라 인수의 부호에 따라 -1 또는 1 만 산출합니다. 실제로 그것은 0이 아닌 실수에 대해서만 유효합니다. 일반적으로 signum정규화 함수로 더 잘 이해됩니다.

      abs (signum a) ≡ 1   -- unless a≡0
      signum a * abs a ≡ a -- This is required to be true for all Num instances
    

    Haskell 2010 보고서의 6.4.4 절 에는 명시 적으로 유효한 Num 인스턴스를 보유하기위한 최종 동등성이 명시 적으로 필요합니다.


일부 라이브러리, 특히 선형hmatrixNum 클래스가 무엇인지에 대해 훨씬 이해하기 쉽지 않습니다 . 산술 연산자를 과부하하는 방법 으로 취급합니다. +- 는 매우 간단하지만, 다른 방법을 사용할 때 이미 * 가 번거로워집니다. 예를 들어, * 는 행렬 곱셈 또는 요소 별 곱셈을 의미합니까?
논 - 숫자 인스턴스를 정의하는 것은 틀림없이 나쁜 생각입니다. VectorSpace 와 같은 전용 클래스를 고려하십시오.


특히, 부호없는 타입의 "네가티브"는 큰 양수로 둘러 (-4 :: Word32) == 4294967292 예 : (-4 :: Word32) == 4294967292 .

이 널리 충족되지 : 벡터 유형은 실제 집합이 없습니다. 논쟁의 여지가있는 Num 인스턴스는 일반적으로 abssignum 요소별로 정의합니다. 수학적으로 말하면 실제로 이해가되지 않습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow