The meaning of <= vs. => in Haskell - haskell

I'm relatively new to Haskell; what does the <= syntax represent and what is the difference between <= and =>? Examples of both would be helpful.

The two are completely unrelated; they just seem related because of ASCII. It makes more sense if you look at their Unicode equivalents:
=> is an arrow: ⇒. It's used to specify constraints in type signatures:
Eq a => a -> a -> Bool
The Eq a => in the above signature means that the type variable a can be any type that is an instance of the Eq class. That is, any type that either has deriving (Eq) or an explicit instance like instance Eq Type where ....
In function signatures, -> specifies a normal argument while => specifies constraints in the signature. In the above example (Eq a => a -> a -> Bool), the function takes two arguments of type a and gives us a Bool. The Eq a => part is not an explicit argument to the function; it just tells us that a must be part of Eq (that is, it must be comparable with ==).
<= is less than or equal to. That is, it's ≤, not ⇐. It's a normal function in the standard library that's part of the Ord class:
λ> :t (<=)
(<=) :: Ord a => a -> a -> Bool
You can use it in a normal expression:
λ> 10 <= 12
True
The only reason they seem symmetrical is because the ASCII approximation of ≤ and ⇐ are the same, but that's just a limitation in notation. Otherwise, they're completely unrelated.
You can use the unambiguous Unicode symbols in your code. The UnicodeSyntax extension enables using ⇒ for => and the base-unicode-symbols package contains Unicode versions of standard library functions including ≤ for <=.

They're completely different things.
=> (as well as ->) is built-in type-level syntax. It's used for denoting constraints. For instance, the signature
abs :: Num a => a -> a
tells you that the abs function takes a value of type a and yields a value of the same type, under the condition a is a number type (i.e., fulfills the Num a constraint). Such a constraint will usually be† a type class; in this case
class Num a where
...
You can read the => arrow as a sort-of function mapping, too: abs first takes the information of what specific sort of number a is as an “implicit argument”, then one such number as an explicit argument, and only then gives the result.
<= is not syntax, it's just an infix operator that's defined in the standard library. Specifically it's the less-than operator, which mathematicians write &leq;.You can look up such operators on Hayoo, no need to ask questions about them.
†Strictly speaking, a class is not a constraint but a “constraint constructor”, i.e. a type-level function whose result is of kind Constraint. For instance, Num :: * -> Constraint applied to e.g. Int :: * means that Num Int is a constraint. (Those are not type signatures but kind signatures, i.e. “types of type-level things”.)

Related

How to check instance of fractional class for zero value in haskell?

If i have a value which is restricted to be fractional, is there a way i can check it either for being a zero value or for some neutral value? I'm trying to implement safe division with signature like this:
safe_idv :: (Fractional q) => q -> q -> Maybe q
I've checked at Hoogle if there is some method in minimal definition which can help, but to no avail.
Thanks in advance
Update: Since the question caused some confusion, I want to avoid changing the constraints on q, and pattern matching still requires Eq (i guess implicitly).
For following definition:
safe_div :: (Fractional q) => q -> q -> Result q
safe_div a 0 = Err ["dvision by zero"]
safe_div a b = Ok (a / b)
following error is raised:
* Could not deduce (Eq q) arising from the literal `0'
from the context: Fractional q
bound by the type signature for:
safe_div :: forall q. Fractional q => q -> q -> Result q
at AST2.hs:11:1-48
Possible fix:
add (Eq q) to the context of
the type signature for:
safe_div :: forall q. Fractional q => q -> q -> Result q
* In the pattern: 0
In an equation for `safe_div':
safe_div a 0 = Err ["dvision by zero"]
With the signature safe_div :: (Fractional q) => q -> q -> Result q, you can only use methods from Fractional or its superclasses on your q values.
(Or other predefined functions that impose no more constraints than Fractional, but those will ultimately have to be implemented by the class methods. So they can't do anything you couldn't do directly with the methods yourself.)
From Fractional itself that gives us:
(/) :: Fractional a => a -> a -> a
recip :: Fractional a => a -> a
fromRational :: Fractional a => Rational -> a
Well none of those look terribly helpful. But Num is a superclass of Fractional, so we have those methods too:
(+) :: Num a => a -> a -> a
(-) :: Num a => a -> a -> a
(*) :: Num a => a -> a -> a
negate :: Num a => a -> a
abs :: Num a => a -> a
signum :: Num a => a -> a
fromInteger :: Num a => Integer -> a
These also aren't going to help us. abs and signum at first seem like they might, since their "purpose" is telling us certain properties about the number; signum even says this:
For real numbers, the signum is either -1 (negative), 0 (zero) or 1 (positive).
Which sounds exactly the kind of thing we want! The only trouble is that signum communicates the result of its inspection as a value of the same type. If we couldn't tell if our number x is equal to zero, how are we going to tell whether signum x is equal to zero? We're right back at the problem we started with.
The fact is every single method of both Fractional and Num only ever returns a value of the (unknown) type implementing the class. That basically means if you don't know what they type actually is, it's impossible to get any information out of them; the only thing you can do with a value of an unknown Fractional type is pass it to another Fractional (or Num) method, which will also only give you back a value of the same unknown type. There's no way to compare it to anything (which would require something returning a Bool, Ordering, or at least a Maybe, Either, etc). There's no way to convert it to text so it can be shown to a user (which would require something returning a String, Text, etc). You can do further calculations, but the only thing we can ever learn is that the calculation didn't error out, and only by trying it and hoping (which is exactly what you're trying to avoid!).
The only way you can implement your desired function is to add more constraints. Eq is exactly the class of types which can be compared, and you want to compare values of your type, so it just makes sense that you will have to constrain your function to operate within this class of types.
However, anyone calling this function polymorphically is in the same boat. It's very useful for intermediate functions (like this one) to work with unknown Fractional types, so that they can be called with any fractional type. But at the outermost level where someone first decided to call one of these functions, it's only ever useful to call these with a concrete type they actually know something about. Nobody wants to do calculations on numbers where they can't inspect the result in any way! This means that even though your safe_div function (as it is currently written) cannot assume any details of any particular type (such as whether it can be compared for equality), it in fact will only ever realistically be called with specific types like Double, Float, etc, all of which do support Eq. So in practice adding the Eq constraint is hardly limiting who can call it.
I imagine the reason you don't want to change the constraint is that you've already coded up functions where you use this, and they only have Fractional constraints (meaning they can't call safe_div :: (Eq a, Fractional a) => a -> a -> Result a). Unfortunately they'll have to be updated to add the Eq constraint too. The fact is that the interface of just Fractional gives only the ability to do basic arithmetic. To do comparisons and branching calculations you need more. So all your functions that want to do more than basic arithmetic (and that includes any that call anything that does more than basic arithmetic, not just ones that do the comparison and branching themselves) need more constraints than just Fractional. Fortunately the same reasoning as above applies: it is extremely unlikely that you would ever need to call any of these functions with a type that doesn't support Eq, so there really is very little point in resisting the additional constraint.

Confusion with Haskell classes

I am confused with classes in Haskell as follows.
I can define a function that takes an Integral argument, and successfully supply it with a Num argument:
gi :: Integral a => a -> a
gi i = i
gin = gi (3 :: Num a => a)
I can define a function that takes a Num argument, and successfully supply it with an Integral argument:
fn :: Num a => a -> a
fn n = n
fni = fn (3 :: Integral a => a)
I can define an Integral value and assign a Num to it
i :: Integral a => a
i = (3 :: Num a => a)
But if I try to define a Num value, then I get a parse error if I assign an Integral value to it
- this doesn't work
n :: Num a => a
n = (3 :: Integral a => a)
Maybe I am being confused by my OO background. But why do function variables appear to let you go 'both ways' i.e. can provide a value of a subclass when a superclass is 'expected' and can provide a value of a superclass when a subclass is expected, whereas in value assignment you can provide a superclass to a subclass value but can't assign a subclass to a superclass value?
For comparison, in OO programming you can typically assign a child value to a parent type, but not vice-versa. In Haskell, the opposite appears to be the case in the second pair of examples.
The first two examples don't actually have anything to do with the relationship between Num and Integral.
Take a look at the type of gin and fni. Let's do it together:
> :t gin
gin :: Integer
> :t fni
fni :: Integer
What's going on? This is called "type defaulting".
Technically speaking, any numeric literal like 3 or 5 or 42 in Haskell has type Num a => a. So if you wanted it to just be an integer number dammit, you'd have to always write 42 :: Integer instead of just 42. This is mighty inconvenient.
So to work around that, Haskell has certain rules that in certain special cases prescribe concrete types to be substituted when the type comes out generic. And in case of both Num and Integral the default type is Integer.
So when the compiler sees 3, and it's used as a parameter for gi, the compiler defaults to Integer. That's it. Your additional constraint of Num a has no further effect, because Integer is, in fact, already an instance of Num.
With the last two examples, on the other hand, the difference is that you explicitly specified the type signature. You didn't just leave it to the compiler to decide, no! You specifically said that n :: Num a => a. So the compiler can't decide that n :: Integer anymore. It has to be generic.
And since it's generic, and constrained to be Num, an Integral type doesn't work, because, as you have correctly noted, Num is not a subclass of Integral.
You can verify this by giving fni a type signature:
-- no longer works
fni :: Num a => a
fni = fn (3 :: Integral a => a)
Wait, but shouldn't n still work? After all, in OO this would work just fine. Take C#:
class Num {}
class Integral : Num {}
class Integer : Integral {}
Num a = (Integer)3
// ^ this is valid (modulo pseudocode), because `Integer` is a subclass of `Num`
Ah, but this is not a generic type! In the above example, a is a value of a concrete type Num, whereas in your Haskell code a is itself a type, but constrained to be Num. This is more like a C# interface than a C# class.
And generic types (whether in Haskell or not) actually work the other way around! Take a value like this:
x :: a
x = ...
What this type signature says is that "Whoever has a need of x, come and take it! But first name a type a. Then the value x will be of that type. Whichever type you name, that's what x will be"
Or, in plainer terms, it's the caller of a function (or consumer of a value) that chooses generic types, not the implementer.
And so, if you say that n :: Num a => a, it means that value n must be able to "morph" into any type a whatsoever, as long as that type has a Num instance. Whoever will use n in their computation - that person will choose what a is. You, the implementer of n, don't get to choose that.
And since you don't get to choose what a is, you don't get to narrow it down to be not just any Num, but an Integral. Because, you know, there are some Nums that are not Integrals, and so what are you going to do if whoever uses n chooses one of those non-Integral types to be a?
In case of i this works fine, because every Integral must also be Num, and so whatever the consumer of i chooses for a, you know for sure that it's going to be Num.

Why can I call a function from a typeclass instance directly in the REPL (like compare from Ord)?

When I am in a REPL like GHCI with Prelude, and I write
*> compare 5 7
LT
Why can I call that function (compare) like that directly in the REPL?
I know that compare is defined in typeclass Ord. The typeclass definition for Ord of course shows that it is a subclass of Eq.
Here is my line of reasoning:
5 has type Num a => a, and Num typeclass is not a subclass of Eq.
Also,
Prelude> :t (compare 5)
(compare 5) :: (Num a, Ord a) => a -> Ordering
So, there is an additional constraint imposed here when I apply a numeric type argument. when I call compare 5 7, the types of the arguments are narrowed to something that does have an instance of Ord. I think the narrowing happens to the default concrete type associated with the typeclass: in the case of Num, this is Integer, which has an instance of Real, which has an instance of Ord.
However, coming from a non-functional programming background, I would have imagined that I would have to call compare on one of the numbers (like calling it on an object in OOP). If 5 is Integer, which does implement Ord, then why do I call compare in the REPL itself? This is obviously a question related to a paradigm shift for me and I still didn't get it. Hopefully someone can explain.
The type defaulting here comes into play. The interpreter can derive that 5 and 7 need to be of the same type, and members of the Ord and Num typeclass. The default for a Num is Integer, and since Integer is an instance of Ord as well, we can thus use Integer.
The interpreter thus considers 5 and 7 to be Integers here in that case, and thus it can evaluate the function and obtain LT.
GHCi has some additional defaulting rules, described in the GHCi documentation.
Methods like compare are associated with types, not particular values. The compiler needs to be able to deduce the type in order to select the correct typeclass instance, but that doesn't require any special assistance.
The type of compare is
compare :: (Ord a) => a -> a -> Ordering
Thus any of its arguments (of type a) can be used to look up the Ord instance.
As you correctly assumed, in the compare 5 7 example, the types of 5 and 7 default to Integer. Thus a in the compare type is deduced to be Integer and the Ord Integer instance is selected.
This selection does not necessarily go through a function argument. Consider e.g.
read :: (Read a) => String -> a
Here it is the result type that drives instance selection, but the type checker is just fine with it:
> read "(2, 3)" :: (Int, Int)
(2,3)
(What would the OO equivalent be? "(2, 3)".read()?)
In fact, methods don't even have to be functions:
maxBound :: (Bounded a) => a
This is a polymorphic value, not a function:
> maxBound :: Int
9223372036854775807
Class instances are uniquely connected to types, so as long as the type checker has enough information to figure out what that type variable represents, everything works out. That is, in
someMethod :: (SomeClass foo) => ...
foo has to appear somewhere in the type signature ... so the type checker can resolve SomeClass foo from the way someMethod is used at any given point (at least in the absence of certain language extensions).

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.

Polymorphic signature for non-polymorphic function: why not?

As an example, consider the trivial function
f :: (Integral b) => a -> b
f x = 3 :: Int
GHC complains that it cannot deduce (b ~ Int). The definition matches the signature in the sense that it returns something that is Integral (namely an Int). Why would/should GHC force me to use a more specific type signature?
Thanks
Type variables in Haskell are universally quantified, so Integral b => b doesn't just mean some Integral type, it means any Integral type. In other words, the caller gets to pick which concrete types should be used. Therefore, it is obviously a type error for the function to always return an Int when the type signature says I should be able to choose any Integral type, e.g. Integer or Word64.
There are extensions which allow you to use existentially quantified type variables, but they are more cumbersome to work with, since they require a wrapper type (in order to store the type class dictionary). Most of the time, it is best to avoid them. But if you did want to use existential types, it would look something like this:
{-# LANGUAGE ExistentialQuantification #-}
data SomeIntegral = forall a. Integral a => SomeIntegral a
f :: a -> SomeIntegral
f x = SomeIntegral (3 :: Int)
Code using this function would then have to be polymorphic enough to work with any Integral type. We also have to pattern match using case instead of let to keep GHC's brain from exploding.
> case f True of SomeIntegral x -> toInteger x
3
> :t toInteger
toInteger :: Integral a => a -> Integer
In the above example, you can think of x as having the type exists b. Integral b => b, i.e. some unknown Integral type.
The most general type of your function is
f :: a -> Int
With a type annotation, you can only demand that you want a more specific type, for example
f :: Bool -> Int
but you cannot declare a less specific type.
The Haskell type system does not allow you to make promises that are not warranted by your code.
As others have said, in Haskell if a function returns a result of type x, that means that the caller gets to decide what the actual type is. Not the function itself. In other words, the function must be able to return any possible type matching the signature.
This is different to most OOP languages, where a signature like this would mean that the function gets to choose what it returns. Apparently this confuses a few people...

Resources