На самом деле существует три оператора возведения в степень: (^)
, (^^)
и (**)
. ^
- неотрицательное целочисленное возведение в степень, ^^
- целочисленное возведение в степень, а **
- возведение в степень с плавающей точкой:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
Причина заключается в безопасности типов: результаты числовых операций обычно имеют тот же тип, что и входные аргументы. Но вы не можете поднять Int
до степени с плавающей запятой и получить результат типа Int
. И поэтому система типов не позволяет вам сделать это: (1::Int) ** 0.5
выдает ошибку типа. То же самое касается (1::Int) ^^ (-1)
.
Другой способ выразить это: Num
типы закрываются в ^
(они не обязательно должны иметь мультипликативный обратный), Fractional
типы закрываются в ^^
, Floating
типы закрываются в **
. Поскольку для Int
нет экземпляра Fractional
, вы не можете поднять его до отрицательной степени.
В идеале, второй аргумент ^
должен быть статически ограничен, чтобы быть неотрицательным (в настоящее время 1 ^ (-2)
генерирует исключение во время выполнения). Но в натуральных числах типа Prelude
.
нет типа.