Zoeken…


Invoering

In Haskell hebben alle uitdrukkingen (inclusief numerieke constanten en functies die daarop werken) een beslissend type. Tijdens het compileren leidt de typecontrole het type expressie af van de typen elementaire functies waaruit deze is samengesteld. Omdat gegevens standaard onveranderlijk zijn, zijn er geen "type casting" -bewerkingen, maar er zijn functies die gegevens kopiëren en de typen binnen redelijke grenzen generaliseren of specialiseren.

Opmerkingen

De numerieke typeklassehiërarchie

Num bevindt zich aan de basis van de numerieke typeklassehiërarchie. De karakteristieke bewerkingen en enkele veel voorkomende exemplaren worden hieronder weergegeven (standaard geladen met Prelude plus die van 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’

We hebben de Fractional klasse al gezien, waarvoor Num vereist is en de noties van "deling" (/) en wederkerig van een aantal introduceert:

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

De Real klasse modellen ... de echte cijfers. Het vereist Num en Ord , daarom modelleert het een geordend numeriek veld. Als tegenvoorbeeld zijn complexe getallen geen geordend veld (dwz ze hebben geen natuurlijke ordeningsrelatie):

λ> :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 vertegenwoordigt getallen die kunnen worden afgerond

λ> :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 (wat neerkomt op Fractional ) vertegenwoordigt constanten en bewerkingen die mogelijk geen eindige decimale uitbreiding hebben.

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

Let op: terwijl uitdrukkingen zoals sqrt . negate :: Floating a => a -> a zijn volkomen geldig, ze kunnen NaN ("not-a-number") retourneren, wat misschien niet de bedoeling is. In dergelijke gevallen willen we misschien over het complexe veld werken (later getoond).

Basis voorbeelden

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

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

In de bovenstaande voorbeelden leidt de typecontrole een typeklasse in plaats van een concreet type voor de twee constanten. In Haskell is de klasse Num de meest algemene numerieke (omdat deze gehele getallen en reals omvat), maar pi moet tot een meer gespecialiseerde klasse behoren, omdat deze een niet-nul fractioneel deel heeft.

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

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

De betonsoorten hierboven zijn afgeleid door GHC. Meer algemene typen zoals list0 :: Num a => [a] zouden hebben gewerkt, maar zou ook moeilijker te bewaren zijn geweest (bijv. Als iemand een Double op een lijst met Num 's had geplaatst), vanwege de hierboven weergegeven kanttekeningen.

"Kon niet afleiden (Fractional Int) ..."

De foutmelding in de titel is een veel voorkomende beginnersfout. Laten we kijken hoe het ontstaat en hoe het te repareren.

Stel dat we de gemiddelde waarde van een lijst met getallen moeten berekenen; de volgende verklaring lijkt het te doen, maar het zou niet compileren:

averageOfList ll = sum ll / length ll

Het probleem is met de delingsfunctie (/) : de handtekening is (/) :: Fractional a => a -> a -> a , maar in het geval boven de noemer (gegeven door length :: Foldable t => ta -> Int ) is van het type Int (en Int behoort niet tot de Fractional klasse) vandaar de foutmelding.

We kunnen het foutbericht oplossen met fromIntegral :: (Num b, Integral a) => a -> b . Men kan zien dat deze functie waarden van elk type Integral accepteert en overeenkomstige waarden in de klasse Num retourneert:

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

Functie voorbeelden

Wat is het type (+) ?

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

Wat is het type sqrt ?

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

Wat is het type sqrt . fromIntegral ?

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow