Haskell exponentiality

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 type of duplication.

 Prelude> 2^2 4 Prelude> 4**0.5 2.0 
+70
haskell exponentiation exponent
Jun 19 2018-11-11T00:
source share
4 answers

In fact, there are three exponentiation operators: (^) , (^^) and (**) . ^ is a non-negative integral exponentiation, ^^ is an integer exponentiation, and ** is an exponentiation with a floating point:

 (^) :: (Num a, Integral b) => a -> b -> a (^^) :: (Fractional a, Integral b) => a -> b -> a (**) :: Floating a => a -> a -> a 

The reason is type safety: the results of numerical operations are usually of the same type as the input arguments. But you cannot raise Int to a floating point level and get a result of type Int . And so the type system does not allow you to do this: (1::Int) ** 0.5 creates a type error. The same goes for (1::Int) ^^ (-1) .

Another way: Num types are closed in ^ (they do not have to have a multiplicative inverse), Fractional types are closed in ^^ , Floating types are closed in ** . Since there is no Fractional instance for Int , you cannot raise it to negative power.

Ideally, the second argument ^ will be statically bounded by a non-negative (currently 1 ^ (-2) throws an exception at runtime). But there is no type for natural numbers in Prelude .

+105
Jun 19 2018-11-11T00:
source share

A system like Haskell is not strong enough to express three exponentiation operators as one. What you really want is something like this:

 class Exp ab where (^) :: a -> b -> a instance (Num a, Integral b) => Exp ab where ... -- current ^ instance (Fractional a, Integral b) => Exp ab where ... -- current ^^ instance (Floating a, Floating b) => Exp ab where ... -- current ** 

This really does not work, even if you enable the class extension with several parameters, because the selection of the instance should be smarter than Haskell allows.

+26
Jun 19 '11 at 14:14
source share

He does not define two operators - he defines three! From the report:

There are three exponent operations with two arguments: ( ^ ) raises any number to a non-negative integer power, ( ^^ ) raises a fractional number to any integer power, and ( ** ) takes two floating numbers, point arguments. The value of x^0 or x^^0 is 1 for any x , including zero; 0**y - undefined.

This means that there are three different algorithms, two of which give exact results ( ^ and ^^ ), and ** gives approximate results. Choosing which operator to use, you choose which algorithm is called.

+8
Jun 19 2018-11-11T00:
source share

^ requires that his second argument be Integral . If I'm not mistaken, the implementation may be more efficient if you know that you are working with an integral metric. Also, if you want something like 2 ^ (1.234) , although your base is integral, 2, your result will obviously be fractional. You have more options so you can have a tighter control over which types are included in and out of your exponential function.

A system like Haskell does not have the same purpose as other type systems such as C, Python, or Lisp. Duck typing is (almost) the opposite of Haskell's thinking.

+4
Jun 19 2018-11-11T00:
source share



All Articles