Поиск…


Вступление

В Haskell все выражения (включая числовые константы и функции, действующие на них) имеют разрешимый тип. Во время компиляции тип-checker определяет тип выражения из типов элементарных функций, которые его составляют. Так как данные по умолчанию неизменяемы, то нет операций типа «casting», но есть функции, которые копируют данные и обобщают или специализируют типы в пределах причины.

замечания

Числовая иерархия типов

Num сидит в корневой строке иерархии типов. Его характерные операции и некоторые общие примеры показаны ниже (те, которые загружаются по умолчанию с 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’

Мы уже видели класс Fractional , который требует Num и вводит понятия «деления» (/) и обратного числа:

λ> :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 классы моделей .. действительные числа. Он требует Num и Ord , поэтому он моделирует упорядоченное числовое поле. В качестве контрпримера комплексные числа не являются упорядоченным полем (т. Е. Не имеют естественного отношения упорядочения):

λ> :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 абсолютно верны, они могут возвращать NaN («не-число»), что может быть не предполагаемым поведением. В таких случаях мы, возможно, захотим работать над полем Комплекс (показано ниже).

Основные примеры

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

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

В приведенных выше примерах, типа проверка выводит типа вируса класса , а не конкретный типа для двух констант. В Haskell класс Num является наиболее общим численным (поскольку он охватывает целые числа и числа), но pi должен принадлежать к более специализированному классу, поскольку он имеет ненулевую дробную часть.

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

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

Конкретные типы, указанные выше, были выведены GHC. Более общие типы, такие как list0 :: Num a => [a] , сработали бы, но было бы еще сложнее сохранить (например, если бы один из них содержал Double в списке Num s) из-за описанных выше предостережений.

`Не удалось вывести (Fractional Int) ...`

Сообщение об ошибке в заголовке является общей ошибкой начинающего. Давайте посмотрим, как это происходит и как это исправить.

Предположим, нам нужно вычислить среднее значение списка чисел; следующее заявление, похоже, сделает это, но оно не будет компилироваться:

averageOfList ll = sum ll / length ll

Проблема заключается в функции деления (/) : ее сигнатура есть (/) :: Fractional a => a -> a -> a , но в случае выше знаменатель (заданный length :: Foldable t => ta -> Int ) имеет тип IntInt не принадлежит классу 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 :: (Integral a, Floating c) => a -> c


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow