Il y a en fait trois opérateurs de exponentiation: (^)
, (^^)
et (**)
. ^
est une exponentiation intégrale non négative, une exponentiation ^^
entière et une exponentiation à **
virgule flottante:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
La raison est la sécurité de type: 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 an Int
à une puissance à virgule flottante et obtenir un résultat de type Int
. Et donc le système de type vous empêche de faire cela: (1::Int) ** 0.5
produit une erreur de type. Il en va de même (1::Int) ^^ (-1)
.
Une autre façon de dire ceci: les Num
types sont fermés sous ^
(ils ne sont pas obligés d'avoir un inverse multiplicatif), les Fractional
types sont fermés sous ^^
, les Floating
types sont fermés sous **
. Puisqu'il n'y a pas d' Fractional
exemple 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)
lève une exception d'exécution). Mais il n'y a pas de type pour les nombres naturels dans le Prelude
.