수색…


소개

하스켈에서는 모든 표현식 (수치 상수와 그 상수를 다루는 함수를 포함한다)은 결정형이다. 컴파일시에 타입 검사기는 표현식의 타입을 그 타입을 구성하는 기본 함수의 타입으로부터 유추한다. 데이터는 기본적으로 불변이므로 "유형 변환"연산은 없지만 데이터를 복사하고 이성 안에서 유형을 일반화하거나 특수화하는 함수가 있습니다.

비고

숫자 형 클래스 계층 구조

Num 은 숫자 typeclass 계층 구조의 루트에 있습니다. 그것의 특징적인 동작과 몇 가지 일반적인 인스턴스가 아래에 나와 있습니다 (기본적으로 Prelude와 Data.Complex 함께로드됩니다).

λ> :i Num
class Num a where
  (+) :: a -> a -> a
  (-) :: a -> a -> a
  (*) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
  {-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-}
      -- Defined in ‘GHC.Num’
instance RealFloat a => Num (Complex a) -- Defined in ‘Data.Complex’
instance Num Word -- Defined in ‘GHC.Num’
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Int -- Defined in ‘GHC.Num’
instance Num Float -- Defined in ‘GHC.Float’
instance Num Double -- Defined in ‘GHC.Float’

Num 을 필요로하고 "나누기" (/) 와 숫자의 역수라는 개념을 도입 한 Fractional 클래스를 이미 보았습니다.

λ> :i Fractional
class Num a => Fractional a where
  (/) :: a -> a -> a
  recip :: a -> a
  fromRational :: Rational -> a
  {-# MINIMAL fromRational, (recip | (/)) #-}
      -- Defined in ‘GHC.Real’
instance RealFloat a => Fractional (Complex a) -- Defined in ‘Data.Complex’
instance Fractional Float -- Defined in ‘GHC.Float’
instance Fractional Double -- Defined in ‘GHC.Float’

Real 클래스는 실제 수치를 모델링합니다. 그것은 NumOrd 필요로하므로, 주문 된 숫자 필드를 모델링합니다. 반례로서, 복소수는 정렬 된 필드가 아닙니다 (즉 자연 순서 관계를 갖고 있지 않음).

λ> :i Real
class (Num a, Ord a) => Real a where
  toRational :: a -> Rational
  {-# MINIMAL toRational #-}
      -- Defined in ‘GHC.Real’
instance Real Word -- Defined in ‘GHC.Real’
instance Real Integer -- Defined in ‘GHC.Real’
instance Real Int -- Defined in ‘GHC.Real’
instance Real Float -- Defined in ‘GHC.Float’
instance Real Double -- Defined in ‘GHC.Float’

RealFrac 은 반올림 될 수있는 숫자를 나타냅니다.

λ> :i RealFrac
class (Real a, Fractional a) => RealFrac a where
  properFraction :: Integral b => a -> (b, a)
  truncate :: Integral b => a -> b
  round :: Integral b => a -> b
  ceiling :: Integral b => a -> b
  floor :: Integral b => a -> b
  {-# MINIMAL properFraction #-}
      -- Defined in ‘GHC.Real’
instance RealFrac Float -- Defined in ‘GHC.Float’
instance RealFrac Double -- Defined in ‘GHC.Float’

Floating ( Fractional 을 의미)은 유한 십진 확장이없는 상수 및 연산을 나타냅니다.

λ> :i Floating
class Fractional a => Floating a where
  pi :: a
  exp :: a -> a
  log :: a -> a
  sqrt :: a -> a
  (**) :: a -> a -> a
  logBase :: a -> a -> a
  sin :: a -> a
  cos :: a -> a
  tan :: a -> a
  asin :: a -> a
  acos :: a -> a
  atan :: a -> a
  sinh :: a -> a
  cosh :: a -> a
  tanh :: a -> a
  asinh :: a -> a
  acosh :: a -> a
  atanh :: a -> a
  GHC.Float.log1p :: a -> a
  GHC.Float.expm1 :: a -> a
  GHC.Float.log1pexp :: a -> a
  GHC.Float.log1mexp :: a -> a
  {-# MINIMAL pi, exp, log, sin, cos, asin, acos, atan, sinh, cosh,
              asinh, acosh, atanh #-}
      -- Defined in ‘GHC.Float’
instance RealFloat a => Floating (Complex a) -- Defined in ‘Data.Complex’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’

주의 : sqrt . negate :: Floating a => a -> a 와 같은 표현식이 사용됩니다 sqrt . negate :: Floating a => a -> a 는 완벽하게 유효하며 의도 한 동작이 아닐 수있는 NaN ( "not-a-number")을 반환 할 수 있습니다. 그러한 경우에는 복잡한 필드 (나중에 표시됨)를 통해 작업 할 수 있습니다.

기본 예제

λ> :t 1
1 :: Num t => t

λ> :t pi
pi :: Floating a => a

위의 예제에서 유형 검사기는 두 개의 상수에 대한 구체적인 유형이 아닌 유형 클래스를 추론합니다. Haskell에서 Num 클래스는 가장 일반적인 수치 형이고 (정수와 실수를 포함하므로), pi 는 0이 아닌 소수 부분을 가지기 때문에 더 특수화 된 클래스에 속해야합니다.

list0 :: [Integer]
list0 = [1, 2, 3]

list1 :: [Double]
list1 = [1, 2, pi]

위의 구체적인 유형은 GHC에 의해 추론되었습니다. list0 :: Num a => [a] 와 같은 좀 더 일반적인 유형이 효과가 있었지만 위에 표시된주의 사항 때문에 보존하기가 더 어려웠습니다 (예 : NumNum 목록에 Double 을 할당 한 경우).

`Fractional Int를 추론 할 수 없었습니다 ... '

제목의 오류 메시지는 일반적인 초보자 실수입니다. 어떻게 그것이 발생하고 그것을 고치는 지 보자.

숫자 목록의 평균값을 계산해야한다고 가정합니다. 다음과 같은 선언은 그것을 수행하는 것처럼 보이지만 컴파일되지는 않습니다 :

averageOfList ll = sum ll / length ll

문제는 나누기 (/) 함수와 관련이 있습니다. 서명은 (/) :: Fractional a => a -> a -> a 이지만 분모 위에있는 경우 ( length :: Foldable t => ta -> Int ) 형이다 Int (및 Int 받는 속하지 않는 Fractional 클래스) 때문에, 에러 메시지.

우리는 fromIntegral :: (Num b, Integral a) => a -> b 사용하여 오류 메시지를 수정할 수 있습니다. 이 함수는 Integral 타입의 값을 받아들이고 Num 클래스에서 상응하는 타입을 반환한다는 것을 알 수 있습니다 :

averageOfList' :: (Foldable t, Fractional a) => t a -> a
averageOfList' ll = sum ll / fromIntegral (length ll)

함수 예제

(+) 의 유형은 무엇입니까?

λ> :t (+)
(+) :: Num a => a -> a -> a

sqrt 의 유형은 무엇입니까?

λ> :t sqrt
sqrt :: Floating a => a -> a

sqrt . fromIntegral 의 유형은 무엇입니까? sqrt . fromIntegral ?

sqrt . fromIntegral :: (Integral a, Floating c) => a -> c


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