Exponentiation in Haskell - haskell

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

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 of x^0 or x^^0 is 1 for any x, including zero; 0**y is 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.

^ requires its second argument to be an Integral. If I'm not mistaken, the implementation can be more efficient if you know you are working with an integral exponent. Also, if you want something like 2 ^ (1.234), even though your base is an integral, 2, your result will obviously be fractional. You have more options so that you can have more tight control over what types are going in and out of your exponentiation function.
Haskell's type system does not have the same goal as other type systems, such as C's, Python's, or Lisp's. Duck typing is (nearly) the opposite of the Haskell mindset.

Related

Question about the argument type of sqrt and round

following the signature:
sqrt :: Floating a => a -> a
why is (sqrt 2) legal? Isn't the number 2 a Integer which definitely doesn't satisfy Floating? Same Question about round, round (sqrt 2) is legal, sqrt returns type Floating but round needs ReadFrac.
round :: (RealFrac a, Integral b) => a -> b
The literal 2 is of type Num a => a. That is, it can be any numerical type. Specifically, Haskell will take the integer value 2 and call fromInteger on it (which is defined for any Num). So when you write
sqrt 2
Internally, what's happening is
sqrt (fromInteger 2) :: Floating a => a
And if you force the value, such as in GHCi, you'll get a Double since that's the default for Floating.
Likewise, the type of round (sqrt 2) is going to be Integral b => b and is going to require the sqrt 2 type to be RealFrac a => a. There exist types which are both RealFrac and Floating, so that's not a contradiction. In particular, GHC will happily default to Double here for the same reason as before. If you force the value to be printed, the entire result (Integral b => b) will default to Integer.
It's important to remember that all of these are universally quantified. Floating a => a doesn't mean "this is some floating type and that's all I know". It means "if you have any floating type, I can produce a value of that type". You get to choose which floating type to use, so if a constraint comes along later and says the value is also RealFrac a => a, that's fine because we've simply constrained ourselves to be both Floating and RealFrac. This is contrary to a language like Java, where if I have a value of some interface type, say Comparable, then all I can conclude is that it's some Comparable type, not that it works for all of them.

Polymorphism: a constant versus a function

I'm new to Haskell and come across a slightly puzzling example for me in the Haskell Programming from First Principles book. At the end of Chapter 6 it suddenly occurred to me that the following doesn't work:
constant :: (Num a) => a
constant = 1.0
However, the following works fine:
f :: (Num a) => a -> a
f x = 3*x
I can input any numerical value for x into the function f and nothing will break. It's not constrained to taking integers. This makes sense to me intuitively. But the example with the constant is totally confusing to me.
Over on a reddit thread for the book it was explained (paraphrasing) that the reason why the constant example doesn't work is that the type declaration forces the value of constant to only be things which aren't more specific than Num. So trying to assign a value to it which is from a subclass of Num like Fractional isn't kosher.
If that explanation is correct, then am I wrong in thinking that these two examples seem completely opposites of each other? In one case, the type declaration forces the value to be as general as possible. In the other case, the accepted values for the function can be anything that implements Num.
Can anyone set me straight on this?
It can sometimes help to read types as a game played between two actors, the implementor of the type and the user of the type. To do a good job of explaining this perspective, we have to introduce something that Haskell hides from you by default: we will add binders for all type variables. So your types would actually become:
constant :: forall a. Num a => a
f :: forall a. Num a => a -> a
Now, we will read type formation rules thusly:
forall a. t means: the caller chooses a type a, and the game continues as t
c => t means: the caller shows that constraint c holds, and the game continues as t
t -> t' means: the caller chooses a value of type t, and the game continues as t'
t (where t is a monomorphic type such as a bare variable or Integer or similar) means: the implementor produces a value of type a
We will need a few other details to truly understand things here, so I will quickly say them here:
When we write a number with no decimal points, the compiler implicitly converts this to a call to fromInteger applied to the Integer produced by parsing that number. We have fromInteger :: forall a. Num a => Integer -> a.
When we write a number with decimal points, the compiler implicitly converts this to a call to fromRational applied to the Rational produced by parsing that number. We have fromRational :: forall a. Fractional a => Rational -> a.
The Num class includes the method (*) :: forall a. Num a => a -> a -> a.
Now let's try to walk through your two examples slowly and carefully.
constant :: forall a. Num a => a
constant = 1.0 {- = fromRational (1 % 1) -}
The type of constant says: the caller chooses a type, shows that this type implements Num, and then the implementor must produce a value of that type. Now the implementor tries to play his own game by calling fromRational :: Fractional a => Rational -> a. He chooses the same type the caller did, and then makes an attempt to show that this type implements Fractional. Oops! He can't show that, because the only thing the caller proved to him was that a implements Num -- which doesn't guarantee that a also implements Fractional. Dang. So the implementor of constant isn't allowed to call fromRational at that type.
Now, let's look at f:
f :: forall a. Num a => a -> a
f x = 3*x {- = fromInteger 3 * x -}
The type of f says: the caller chooses a type, shows that the type implements Num, and chooses a value of that type. The implementor must then produce another value of that type. He is going to do this by playing his own game with (*) and fromInteger. In particular, he chooses the same type the caller did. But now fromInteger and (*) only demand that he prove that this type is an instance of Num -- so he passes off the proof the caller gave him of this and saves the day! Then he chooses the Integer 3 for the argument to fromInteger, and chooses the result of this and the value the caller handed him as the two arguments to (*). Everybody is satisfied, and the implementor gets to return a new value.
The point of this whole exposition is this: the Num constraint in both cases is enforcing exactly the same thing, namely, that whatever type we choose to instantiate a at must be a member of the Num class. It's just that in the definition constant = 1.0 being in Num isn't enough to do the operations we've written, whereas in f x = 3*x being in Num is enough to do the operations we've written. And since the operations we've chosen for the two things are so different, it should not be too surprising that one works and the other doesn't!
When you have a polymorphic value, the caller chooses which concrete type to use. The Haskell report defines the type of numeric literals, namely:
integer and floating literals have the typings (Num a) => a and
(Fractional a) => a, respectively
3 is an integer literal so has type Num a => a and (*) has type Num a => a -> a -> a so f has type Num a => a -> a.
In contrast, 3.0 has type Fractional a => a. Since Fractional is a subclass of Num your type signature for constant is invalid since the caller could choose a type for a which is Num but not Fractional e.g. Int or Integer.
They don't mean the opposite - they mean exactly the same ("as general as possible"). Typeclass gives you all guarantees that you can rely upon - if typeclass T provides function f, you can use it for all instances of T, but even if some of these instances are members of G (providing g) as well, requiring to be of T typeclass is not sufficient to call g.
In your case this means:
Members of Num are guaranteed to provide conversion from integers (i.e. default type for integral values, like 1 or 1000) - with fromInteger function.
However, they are not guaranteed to provide conversion from rational numbers (like 1.0) - Fractional typeclass does provide this as fromRational function, but it doesn't really matter, as you use only Num.

Why does (-) fail to typecheck when I place a Double Matrix on the left and a Double on the right?

Since hmatrix provides an instance of Num for Matrix types, I can express element-wise subtraction like:
m = (2><2)[1..] :: Double Matrix
m' = m - 3
That works great, as 3 is a Num, and results in a matrix created by subtracting 3 from each element of m.
Why does this not also work:
m' = m - (3::Double)
The error I'm getting is:
Couldn't match expected type ‘Matrix Double’
with actual type ‘Double’
In the second argument of ‘(-)’, namely ‘(3 :: Double)’
In the expression: m - (3 :: Double)
I expected the compiler to understand that a Double is also a Num. Why is that seemingly not the case?
What happens when you do m - 3 with m :: Matrix Double is that 3 :: Matrix Double. The fact that Matrix Double is an instance of Num means that the compilers knows how to translate the litteral 3. However when you do m - (3 :: Double), you get a type error because (-) :: (Num a) => a -> a -> a, so the type of the element you subtract must be instances of Num and match. Hence you can subtract two Doubles, two Matrix Doubles but not a Matrix Double and a Double.
After all, this seems fairly logical to me, it doesn't make sense to subtract a matrix and a scalar.
This is a common misunderstanding of people new to Haskell's style of typeclass based overloading, especially those who are used to the subclass-based overloading used in popular OO languages.
The subtraction operator has type Num a => a -> a -> a; so it takes two arguments of any type that is in the type class Num. It seems like what is happening when you do m - 3 is that the subtraction operator is accepting a Matrix Double on the left and some simple numeric type on the right. But that is actually incorrect.
When a type signature like Num a => a -> a -> a uses the same type variable multiple times, you can pick any type you like (subject to the contstraints before the =>: Num a in this case) to use for a but it has to be the exact same type everywhere that a appears. Matrix Double -> Double -> ??? is not a valid instantiation of the type Num a => a -> a -> a (and if it were, how would you know what it returned?).
The reason m - 3 works is that because both arguments have to be the same type, and m is definitely of type Matrix Double, the compiler sees that 3 must also be of type Matrix Double. So instead of using the 3 appearing in the source text to build a Double (or Integer, or one of many other numeric types), it uses the source text 3 to build a Matrix Double. Effectively the type inference has changed the way the compiler reads the source code text 3.
But if you use m' = m - (3::Double) then you're not letting it just figure out what type 3 must have to make the use of the subtraction operator valid, you're telling it that this 3 is specifically a Double. There's no way both facts to be true (your :: Double assertion and the requirement that the subtraction operator gets two arguments of the same type), so you get a type error.

Why the result of (/) function may also be Integral?

Consider:
> :t (/)
(/) :: Fractional a => a -> a -> a
and
> :t (round 10 / 100)
(round 10 / 100) :: (Fractional a, Integral a) => a
How could (/) result in Integral?
I believe you are misreading the result type
result :: (Fractional a, Integral a) => a
This type is a "contract" between the user of result and the implementor of result. Let's take it apart:
The user must first choose a type a
The user must then prove that the chosen a belongs to classes Fractional and Integral. Roughly, this means that the user has to provide a definition for the methods of such classes.
Finally, the implementor will provide a value of type a.
Part 2 is the crucial step. As we can see, the type of result does not promise to construct some value whose type is both a fractional and an integral. Quite the opposite: it requires that whoever wants to use that result value has to find such a type.
Concretely, this means that result is unusable. GHC does not raise a type error because it has no deep knowledge about the intended meaning of the type classes. Indeed, from a purely theoretical point of view, one could define a custom type and provide fractional/integral instances, e.g.
data A = A0 | A1 | A2
instance Num A where
...
instance Fractional A where
...
instance Integral A where
...
with some weird implementation, such as performing fractional operations modulo 3, but not integral operations.
Anyway, since something like A could be defined, GHC can not reject the type above.

How is the Floating typeclass different from Double?

*User> :t sqrt
sqrt :: Floating a => a -> a
I don't understand what Floating a => a -> a is trying to tell me.
My professor told me sqrt can be thought of like sqrt :: Double -> Double.
And it does act like that but what does Floating a => a -> a mean?
Thank you
A useful thing to try interactively in ghci is the :info <something> command, which can sometimes tell you helpful things.
> :info Floating
class Fractional a => Floating a where
pi :: a
exp :: a -> a
log :: a -> a
sqrt :: a -> a
(**) :: a -> a -> a
---------------------------------------- loads more stuff
-- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’
What does this mean? Floating is a type class. There is more than one type of floating point numbers. Indeed, two come as standard: Float and Double, where Double gives you twice the precision of Float. The a in Floating a stands for any type, and the big list of operations (including sqrt) is an interface which any instance of the class must implement. The fact that sqrt is in the interface for Floating means that it can always and only be used for instances of Floating. That is, to you its type is given as you say
sqrt :: Floating a => a -> a
The => syntax signals a constraint, here Floating a to its left. The type says
for any type a which is an instance of Floating, given an input of type a, the output will have type a
You can specialize this type by filling in a with any type for which the constraint Floating a can be satisfied, so the following are both true
sqrt :: Float -> Float
sqrt :: Double -> Double
Now, Float and Double are represented by different bit-patterns, so the computational mechanisms for taking square roots is different in each case. It's handy not to have to remember different names for the different versions used for different types. The "constraint" Floating a really stands for the record (or dictionary) of the implementations for type a of all the operations in the interface. What the type of sqrt is really saying is
given a type a and a dictionary of implementations for all the Floating operations, I'll take an a and give you an a
and it works by extracting the relevant sqrt implementation from the dictionary and using it on the given input.
So the => signals a function type with an invisible dictionary input just as -> signals a function type with a visible value input. You don't (indeed, you can't) write the dictionary when you use the function: the compiler figures it out from the type. When we write
sqrt :: Double -> Double
we mean the general sqrt function invisibly applied to the Floating Double dictionary.
Floating is a type class. You can think of it as a collection of numeric types which support the following operations:
sqrt, exp, log, (**)
trig functions: sin, cos, tan, asin, acos, atan, pi
hyperboolic trig functions: sinh, cosh, tanh, asinh, acosh, atanh
If you know Java, then you can think of a typeclass like Floating as Java interface.
Examples of types which are in the Floating class:
Float (single precision floating point)
Double
Complex Double
Complex Double are complex numbers where the real and imaginary parts are represented with Double values.
Examples of types which are not in the Floating class:
Int
Char
String
The signature sqrt :: Floating a => a -> a translates roughly as:
For any type a, if a is in the Floating class, then sqrt is a function taking an a and returning an a
This means that you can write code like this:
root a b c = (-b + sqrt (b*b - 4*a*c)) / (2*a)
and you can call root with either Double, Float or Complex Double arguments (provided they are all of the same type). For example:
import Data.Complex
ghci> let root a b c = (-b + sqrt (b*b - 4*a*c)) / (2*a)
ghci> root 1 0 1 :: Double
NaN -- can't represent sqrt -1 as a Double
ghci> root 1 0 1 :: Complex Double
0.0 :+ 1.0 -- sqrt -1 as a Complex number = i
Note how the same expression root 1 0 1 gave different results based on what we forced the return type to be.
Consider this problem instead:
axe :: Log -> (Log, Log)
A function that splits wooden logs in two. Can we generalise this? Turns out we can:
class Splittable l where
axe :: l -> (l,l)
Now axe is not specific to Logs, but can split anything that's soft enough.
instance Splittable Log where
axe = ... -- previous definition, for logs
instance Splittable Neck where
axe = ... -- executable version
For sqrt it's similar: this function sure makes sense for (positive) Doubles, but it can also operate on more general types of numbers. For instance,
> sqrt (-1) :: Double
NaN -- urgh... negative numbers don't have real roots!
> :m +Data.Complex
> sqrt (-1) :: Complex Double
(- 0.0) :+ 1.0
You can think of the part to the left of => as a set of constraints.
Floating a means: the type a must be an instance of the Floating type class. I assume you know what type classes are. If not, see this or search for "haskell type classes"
So: Floating a => a -> a means: given any type a that is an instance of the Floating type class, this function has type a -> a. Because Haskell has more than one type of floating point numbers, this "more generic" type is used. One instance of Floating is indeed, Double.
The Floating a bit is a constraint requiring the type a to belong to the class of types that represent, or are viewable as, floating point numbers, that is, a belongs to the Floating class, or, a is an instance of Floating.
You can, sort of, think of type classes like interfaces — a type a either implements that "interface" or it doesn't; now sqrt simply works on any type a that implements Floating.
But don't get too carried away with this analogy — it ends almost as quickly as it begins: there are more differences between, say Java, interfaces and Haskell type classes than there are similarities, but the analogy is useful for "getting on board".
To sum up, Floating a => a -> a means: a function from values of any type a to values of that same type a (i.e. a -> a), for as long as the type a resembles a floating point.
Doing :i Floating in a GHCi REPL will, in addition to the structure of the Floating type class, show you a list of the types that implement it:
Prelude> :i Floating
class Fractional a => Floating a where
... LOTS OF FUNCTION DECLARATIONS ...
-- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’
Constraints have a language of their own in Haskell and can be composed, so you can have (Floating a, Floating c, Foo a, Bar [b], Baz c) => a -> [b] -> (a, c) or some other crazy imaginary type signature.

Resources