Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type of `==` in Haskell should be `Eq a b => a -> b -> Bool`

The type of (==) is Eq a => a -> a -> Bool but I can imagine a more general version Eq a b => a -> b -> Bool that is false when the types don't match and is just the usual kind of equality when the types match. Why is this not the case?

like image 476
David K. Avatar asked Dec 13 '14 03:12

David K.


People also ask

What is EQ type in Haskell?

The Eq typeclass provides an interface for testing for equality. Any type where it makes sense to test for equality between two values of that type should be a member of the Eq class. All standard Haskell types except for IO (the type for dealing with input and output) and functions are a part of the Eq typeclass.

How do I check my type in Haskell?

If you need to figure out what the type of an object is in a Haskell program, I hope this is helpful. Note that if you are in GHCI, you can just put :type before your expression to determine the expression's type, or use :set +t to see the type of every expression in GHCI.

How types are used in Haskell?

In Haskell, every statement is considered as a mathematical expression and the category of this expression is called as a Type. You can say that "Type" is the data type of the expression used at compile time. To learn more about the Type, we will use the ":t" command.

What is a class in Haskell?

What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.


2 Answers

We can define that in terms of both Eq and Typeable from Data.Typeable. We can compare the types of things that are Typeable to check that they are the same type.

(?==) :: (Eq b, Typeable a, Typeable b) => a -> b -> Bool
x ?== y = cast x == Just y

cast checks that a value of one Typeable type is actually the same type as another. It returns Just the input if they are the same type or Nothing if the types are different.

Here are a few examples demonstrating the desired behavior.

> 7 ?== 7
True

> 7 ?== "hello"
False

> 7 ?== 5
False

> (7 :: Int) ?== (7 :: Integer)
False
like image 73
Cirdec Avatar answered Nov 11 '22 05:11

Cirdec


(==) :: Eq a b => a -> b -> Bool wouldn't be of as much use as you'd think.

To determine an instance of 2-parameter Eq, you need to know both types (well enough to match an instance). Any callers of this == would need to either concretely know a and b, or pass the constraint on in their interface; then their own callers either need to know what a and b are, or pass the constraint on.... at some point the Eq instance has to be selected, rather than provided via a constraint, and that involves knowing a and b at compile time.

At that point, why would you bother? If you know a and b are the same, then a single parameter Eq is enough to compare them. And if you know they are different, then you know the answer is False and you don't need any instance to tell you that. And if you don't know whether they are the same or different, then by definition you don't know enough to select an Eq instance, so you can't call == (or an Eq-constrained function) at all!

So this wouldn't help you get an a and b of unknown types (that implement equality) from separate sources and then compare them. They would have had to come together with an Eq a b instance, which is effectively a compile-time proof of whether they are the same type or not,

The Typeable version in @Cirdec's answer is very different, and much more useful. Here each type independentlly supports Typeable and one of them supports single-parameter Eq; you can get these two values from two different sources where you don't know if they are the same or not, but you know that you can check the type of each; the a source has to know a well enough to select a Typeable instance, and the b source has to know b well enough to select Typeable and Eq instances, but neither source has to know anything about the other type, and no code has to know both types at once well enough to tell whether they are the same (at compile time). The 2-parameter Eq forces both types to be known at once, somewhere, which would make it near-worthless.

like image 28
Ben Avatar answered Nov 11 '22 03:11

Ben