En realidad, existen tres operadores de exponenciación: (^)
, (^^)
y (**)
. ^
es exponenciación con exponente entero no negativo, ^^
es exponenciación con exponente entero, y **
es exponenciación con punto flotante:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
La razón es la seguridad de tipos: los resultados de operaciones numéricas generalmente tienen el mismo tipo que el argumento de entrada. Pero no puedes elevar un Int
a una potencia de punto flotante y obtener un resultado de tipo Int
. Por lo tanto, el sistema de tipos te impide hacer esto: (1::Int) ** 0.5
produce un error de tipo. Lo mismo ocurre con (1::Int) ^^ (-1)
.
Otra forma de ver esto es: los tipos Num
están cerrados bajo ^
(no necesitan tener un inverso multiplicativo), los tipos Fractional
están cerrados bajo ^^
, los tipos Floating
están cerrados bajo **
. Dado que no hay una instancia Fractional
para Int
, no puedes elevarlo a una potencia negativa.
Lo ideal sería que el segundo argumento de ^
estuviera estáticamente restringido a ser no negativo (actualmente, 1 ^ (-2)
arroja una excepción en tiempo de ejecución). Pero no hay un tipo para números naturales en el Prelude
.