En realidad, hay tres operadores de exponenciación: (^)
, (^^)
y (**)
. ^
es exponenciación integral no negativa, ^^
es exponenciación entera y **
es exponenciación de 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 las operaciones numéricas generalmente tienen el mismo tipo que los argumentos de entrada. Pero no puedes elevar una Int
potencia de punto flotante y obtener un resultado de tipo Int
. Y así, el sistema de tipos le impide hacer esto: (1::Int) ** 0.5
produce un error de tipo. Lo mismo vale para (1::Int) ^^ (-1)
.
Otra forma de decir esto: los Num
tipos están cerrados bajo ^
(no es necesario que tengan un inverso multiplicativo), los Fractional
tipos están cerrados bajo ^^
, los Floating
tipos están cerrados bajo **
. Dado que no existe una Fractional
instancia para Int
, no puede elevarlo a una potencia negativa.
Idealmente, el segundo argumento de ^
estaría restringido estáticamente para no ser negativo (actualmente, 1 ^ (-2)
lanza una excepción en tiempo de ejecución). Pero no hay ningún tipo para números naturales en Prelude
.
Int
yInteger
. Para poder tener esas tres declaraciones de instancia, la resolución de la instancia debe usar el retroceso, y ningún compilador de Haskell implementa eso.