Il existe en fait trois opérateurs d'exponentiation : (^)
, (^^)
y (**)
. ^
est une exponentiation intégrale non négative, ^^
est une exponentiation entière, et **
est une exponentiation en virgule flottante :
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
La raison en est la sécurité des types : les résultats des opérations numériques ont généralement le même type que le ou les arguments d'entrée. Mais vous ne pouvez pas lever un Int
à une puissance flottante et obtenir un résultat de type Int
. Et donc le système de type vous empêche de le faire : (1::Int) ** 0.5
produit une erreur de type. Il en va de même pour (1::Int) ^^ (-1)
.
Une autre façon de le dire : Num
sont fermés sous ^
(il n'est pas nécessaire qu'ils aient un inverse multiplicatif), Fractional
sont fermés sous ^^
, Floating
sont fermés sous **
. Puisqu'il n'y a pas de Fractional
instance pour Int
vous ne pouvez pas l'élever à une puissance négative.
Idéalement, le deuxième argument de ^
serait statiquement contraint à être non-négatif (actuellement, 1 ^ (-2)
lance une exception d'exécution). Mais il n'existe pas de type pour les nombres naturels dans l'environnement Prelude
.