Ricerca…


introduzione

In Haskell, tutte le espressioni (che includono costanti e funzioni numeriche che operano su quelle) hanno un tipo decidibile. Al momento della compilazione, il type-checker deduce il tipo di un'espressione dai tipi di funzioni elementari che lo compongono. Poiché i dati sono immutabili per impostazione predefinita, non esistono operazioni di "tipo casting", ma esistono funzioni che copiano dati e generalizzano o specializzano i tipi all'interno della ragione.

Osservazioni

La gerarchia dei tipi tipici numerici

Num trova nella radice della gerarchia dei tipi tipici numerici. Le sue operazioni caratteristiche e alcune istanze comuni sono mostrate di seguito (quelle caricate di default con Preludio più quelle di 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’

Abbiamo già visto la classe Fractional , che richiede Num e introduce le nozioni di "divisione" (/) e reciproca di un numero:

λ> :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’

I Real modelli di classe ... i numeri reali. Richiede Num e Ord , quindi modella un campo numerico ordinato. Come controesempio, i numeri complessi non sono un campo ordinato (cioè non possiedono una relazione di ordinamento naturale):

λ> :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 rappresenta numeri che possono essere arrotondati

λ> :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 (che implica Fractional ) rappresenta costanti e operazioni che potrebbero non avere un'espansione decimale finita.

λ> :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’

Attenzione: mentre espressioni come sqrt . negate :: Floating a => a -> a sono perfettamente validi, potrebbero restituire NaN ("not-a-number"), che potrebbe non essere un comportamento previsto. In questi casi, potremmo voler lavorare sul campo Complesso (mostrato più avanti).

Esempi di base

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

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

Negli esempi sopra, il type-checker deduce una classe tipo piuttosto che un tipo concreto per le due costanti. In Haskell, la classe Num è la più numerica (poiché comprende interi e reali), ma pi deve appartenere a una classe più specializzata, poiché ha una parte frazionaria diversa da zero.

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

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

I tipi concreti sopra sono stati dedotti da GHC. Tipi più generali come list0 :: Num a => [a] avrebbe funzionato, ma sarebbe stato anche più difficile da preservare (ad esempio se si è classificato un Double in un elenco di Num ), a causa delle avvertenze mostrate sopra.

`Impossibile dedurre (Int frazionale) ...`

Il messaggio di errore nel titolo è un errore principiante comune. Vediamo come si presenta e come risolverlo.

Supponiamo di dover calcolare il valore medio di un elenco di numeri; la seguente dichiarazione sembrerebbe farlo, ma non verrebbe compilato:

averageOfList ll = sum ll / length ll

Il problema è con la funzione division (/) : la sua firma è (/) :: Fractional a => a -> a -> a , ma nel caso sopra il denominatore (dato dalla length :: Foldable t => ta -> Int ) è di tipo Int (e Int non appartiene alla classe Fractional ) quindi il messaggio di errore.

Possiamo correggere il messaggio di errore con fromIntegral :: (Num b, Integral a) => a -> b . Si può vedere che questa funzione accetta valori di qualsiasi tipo Integral e restituisce quelli corrispondenti nella classe Num :

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

Esempi di funzioni

Qual è il tipo di (+) ?

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

Qual è il tipo di sqrt ?

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

Qual è il tipo di sqrt . fromIntegral ?

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow