Can someone tell me why the Haskell Prelude defines two separate functions for exponentiation (i.e. ^ and **)? I thought the type system was supposed to eliminate this kind of duplication.
Prelude> 2^2
4
Prelude> 4**0.5
2.0
mod : Returns the modulus of the two numbers. This is similar to the remainder but has different rules when "div" returns a negative number.
Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).
div is a prefix operator that correctly performs integer division, throwing away the remainder.
There are actually three exponentiation operators: (^), (^^) and (**). ^ is non-negative integral exponentiation, ^^ is integer exponentiation, and ** is floating-point exponentiation:
(^) :: (Num a, Integral b) => a -> b -> a (^^) :: (Fractional a, Integral b) => a -> b -> a (**) :: Floating a => a -> a -> a The reason is type safety: results of numerical operations generally have the same type as the input argument(s). But you can't raise an Int to a floating-point power and get a result of type Int. And so the type system prevents you from doing this: (1::Int) ** 0.5 produces a type error. The same goes for (1::Int) ^^ (-1).
Another way to put this: Num types are closed under ^ (they are not required to have a multiplicative inverse), Fractional types are closed under ^^, Floating types are closed under **. Since there is no Fractional instance for Int, you can't raise it to a negative power.
Ideally, the second argument of ^ would be statically constrained to be non-negative (currently, 1 ^ (-2) throws a run-time exception). But there is no type for natural numbers in the Prelude.
Haskell's type system isn't powerful enough to express the three exponentiation operators as one. What you'd really want is something like this:
class Exp a b where (^) :: a -> b -> a instance (Num a, Integral b) => Exp a b where ... -- current ^ instance (Fractional a, Integral b) => Exp a b where ... -- current ^^ instance (Floating a, Floating b) => Exp a b where ... -- current ** This doesn't really work even if you turn on the multi-parameter type class extension, because the instance selection needs to be more clever than Haskell currently allows.
It doesn't define two operators -- it defines three! From the Report:
There are three two-argument exponentiation operations: (
^) raises any number to a nonnegative integer power, (^^) raises a fractional number to any integer power, and (**) takes two floating-point arguments. The value ofx^0orx^^0is 1 for anyx, including zero;0**yis undefined.
This means there are three different algorithms, two of which give exact results (^ and ^^), while ** gives approximate results. By choosing which operator to use, you choose which algorithm to invoke.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With