Suche…


Einführung

In Haskell haben alle Ausdrücke (einschließlich numerischer Konstanten und Funktionen, die auf diese angewendet werden) einen entscheidbaren Typ. Bei der Kompilierung entnimmt der Typprüfer den Typ eines Ausdrucks aus den Typen der Elementarfunktionen, aus denen er besteht. Da Daten standardmäßig unveränderlich sind, gibt es keine "Typumwandlung" -Operationen, aber es gibt Funktionen, die Daten kopieren und die Typen innerhalb eines bestimmten Grunds generalisieren oder spezialisieren.

Bemerkungen

Die numerische Typenklassenhierarchie

Num befindet sich am Stamm der numerischen Typenklassenhierarchie. Seine charakteristischen Operationen und einige häufige Instanzen werden unten gezeigt (die standardmäßig mit Prelude geladenen und die von 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’

Wir haben bereits die Fractional Klasse gesehen, die Num benötigt und die Begriffe "Division" (/) und Kehrwert einer Zahl einführt:

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

Die Real Klasse-Modelle .. die reellen Zahlen. Es erfordert Num und Ord , daher modelliert es ein geordnetes numerisches Feld. Als Gegenbeispiel sind komplexe Zahlen kein geordnetes Feld (dh sie besitzen keine natürliche Ordnungsbeziehung):

λ> :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 für Zahlen, die gerundet werden können

λ> :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 (was " Fractional ) steht für Konstanten und Operationen, die möglicherweise keine endliche dezimale Erweiterung haben.

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

Achtung: Während Ausdrücke wie sqrt . negate :: Floating a => a -> a sind absolut gültig, sie können NaN ("not-a-number") zurückgeben, was möglicherweise nicht beabsichtigt ist. In solchen Fällen möchten wir möglicherweise das Feld "Komplex" (später angezeigt) bearbeiten.

Grundlegende Beispiele

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

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

In den obigen Beispielen, folgert die Typprüfung eine Typ- Klasse anstatt einen konkreten Typ für die beiden Konstanten. In Haskell ist die Num Klasse die allgemeinste numerische (da sie ganze und reelle Zahlen umfasst), aber pi muss zu einer spezialisierteren Klasse gehören, da es einen gebrochenen Anteil ungleich Null hat.

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

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

Die konkreten Typen wurden von GHC abgeleitet. Allgemeinere Typen wie list0 :: Num a => [a] hätten funktioniert, wären aber aufgrund der oben aufgeführten Vorbehalte auch schwieriger zu erhalten (z. B. wenn ein Double auf einer Liste von Num s verbraucht wurde).

"Konnte nicht ableiten (Fractional Int) ..."

Die Fehlermeldung im Titel ist ein häufiger Anfängerfehler. Mal sehen, wie es entsteht und wie man es beheben kann.

Angenommen, wir müssen den Durchschnittswert einer Liste von Zahlen berechnen. Die folgende Deklaration scheint das zu tun, würde aber nicht kompilieren:

averageOfList ll = sum ll / length ll

Das Problem liegt bei der Funktion division (/) : Die Signatur lautet (/) :: Fractional a => a -> a -> a , aber im Fall über dem Nenner (gegeben durch length :: Foldable t => ta -> Int ) ist vom Typ Int (und Int gehört nicht zur Klasse Fractional ), daher die Fehlermeldung.

Wir können die Fehlermeldung mit fromIntegral :: (Num b, Integral a) => a -> b beheben. Man kann sehen, dass diese Funktion Werte eines beliebigen Integral akzeptiert und entsprechende Werte in der Klasse Num zurückgibt:

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

Funktionsbeispiele

Was ist der Typ von (+) ?

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

Was ist der Typ von sqrt ?

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

Was ist der Typ von sqrt . fromIntegral ?

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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow