How do I correctly implement an instance Eq for a data type with constructors? - haskell

I am implementing an instance Eq for MyNum data type that has Fractions and Mixed Numbers as data constructors (each one with its own arguments).
I am also using a helper function to convert from MyNum to Rational. This should help me reduce fractions when doing comparisons in the instance Eq.
The problem is I am getting stuck when creating the instance Eq and I am not sure whether I also have to define a new class Eq for the MyNum data type. The general purpose of the Eq is to compare whether two fractions are equal when simplified with the helper method. Here is what I have so far:
Data Type and Constructors:
data MyNum = Fraction {num :: Integer, denom :: Integer}
| Mixed {whole :: Integer, num:: Integer, denom :: Integer}
Helper:
helper :: MyNum -> Rational
helper (Fraction num denom) = (fromIntegral num ) / (fromIntegral denom)
Current Eq:
instance (Eq n d) => Eq (MyNum n d) where
Fraction n d == Fraction n d = True
-- Mixed _ _ _ == Mixed _ _ _ = True
The above Eq code throws the following error:
MyNum.hs:29:16: error:
* Conflicting definitions for `d'
Bound at: MyNum.hs:29:16
MyNum.hs:29:32
* In an equation for `=='
|
29 | Fraction n d == Fraction n d = True
| ^^^^^^^^^^^^^^^^^

The reason this happens is because you use n and d twice in the head of your == method definition, which is not allowed.
Both Fraction n d and Fraction n d in Fraction n d == Fraction n d = True are patterns, and using the same variable in more than one pattern on the left of the = sign in not allowed.
You would also need to write the type constraints as (Eq n, Eq d) =>…, and not Eq n d, but here it makes no difference since you do not use type parameters anyway, so no Eq constraint is needed at all -- the type of the values used by your MyNum type, which are all Integers, already is an instance of Eq:
instance Eq MyNum where
Fraction n1 d1 == Fraction n2 d2 | n1 == n2 && d1 == d2 = True
-- …
Prolog, which works with unification indeed allows us to use the same variable multiple times in the head, to indicate equality.
But Haskell works with pattern matching, and it is therefore not entirely clear what reusing the same variable would mean, especially since not every type is an instance of Eq.

You might want to exploit your helper function to convert both MyNums into Rationals so that you can compare them:
instance Eq MyNum where
x == y = helper x == helper y
Your type MyNum does not take any parameters, so you can't write Eq (MyNum n d). The n and d are values, arguments for the Fraction data constructor, not the type. Since these values are handled by the helper, we don't need to care about them in the instance definition either.
Note that, for the above instance to work, helper must deal with both forms of number, Fraction and Mixed.
helper:: MyNum -> Rational
helper (Fraction num denom) = fromIntegral num / fromIntegral denom
helper (Mixed whole num denom) = ...

Related

Creating Instance of Eq for custom data type in Haskell

I have made some custom Data types for number representation in Haskell, now I want to implement Eq instances for it, but I am somehow stuck. So I have already made:
data Digit = Zero | One | Two
type Digits = [Digit]
data Sign = Pos | Neg -- Pos fuer Positive, Neg fuer Negative
newtype Numeral = Num (Sign,Digits)
instance Eq Sign where
(==) Pos Pos = True
(==) Neg Neg = True
(==) _ _ = False
instance Eq Digit where
(==) Zero Zero = True
(==) One One = True
(==) Two Two = True
(==) _ _ = False
Now I want to check out the Sign in my custom type Numeral so I tried this:
instance (Eq Sign) => Eq (Numeral) where
(==) Num(x,_)== Num(y,_) = x==y
But I get this error: Parse error in pattern : (==)
Mostly putting what I've already written in the comments in a more fleshed out form:
There are a few problems with your code:
You have to indent the code under the instance declarations. That way you tell the compiler what code belongs to the instance declaration.
In the following line you are asking for a type class constraint on a concrete type (Eq Sign =>). This is not possible in standard Haskell and even if you were to follow the compiler instructions and enable the FlexibleInstances language extension it wouldn't make sense.
instance (Eq Sign) => Eq (Numeral) where
Type class constraints are only used for type variables. For example:
double :: Num a => a -> a
double x = x + x
Here we say, that the function double only works for all types that implement Num. double :: Num Int => Int -> Int on the other hand is redundant, because we already know, that Int has a Num instance. The same for Eq Sign.
For instances such constraints only make sense, if the type you are writing an instance for contains another polymorphic type. Fox example instance Ord a => Ord [a]. Here we would use the Ord instance of the elements of the list to lexiographically order lists.
You can define (==) either in infix or prefix form, but not both. So either (==) (Num (x,_)) (Num (y,_)) = x == y or Num (x,_) == Num (y,_) = x == y.
Newtyping tuples to create a product type is rather strange. Newtypes are usually used if you want to use the functionality that is already present for the more complex underlying type. However here that is not the case, you just want a normal product of Digits and Sign.
You are only comparing the Sign of the numbers. While technically a valid Eq instance, I think you also want to compare the digits of the number probably truncating leading zeros. In the code below I didn't truncate zeros though, to keep it simple.
data Digit = Zero | One | Two
type Digits = [Digit]
data Sign = Pos | Neg
data Numeral = Num Sign Digits
instance Eq Sign where
(==) Pos Pos = True
(==) Neg Neg = True
(==) _ _ = False
instance Eq Digit where
(==) Zero Zero = True
(==) One One = True
(==) Two Two = True
(==) _ _ = False
instance Eq Numeral where
Num s1 x1 == Num s2 x2 = s1 == s2 && x1 == x2

Haskell Eq between different types

I need to use this data structure data D = C Int Float and I need to compare it with an Int, for example a::D == 2.
How can I create an instance to define this kind of Eq ?
Thank you!
I would implement a projection:
getInt :: D -> Int
getInt (C i _) = i
and then compare with it:
getInt myD == 5
you can even include this into a record:
data D = C { getInt :: Int, getFloat :: Float }
if you like
You can't; == has signature a -> a -> Bool, so it can't be used like this.
Using the convertible package you can define
(~==) :: (Convertible a b, Eq b) => a -> b -> Bool
x ~== y = case safeConvert x of
Right x' -> x' == y
Left _ -> False
(==~) :: (Convertible b a, Eq a) => a -> b -> Bool
(==~) = flip (~==)
instance Convertible Int D where ...
-- or D Int depending on what you have in mind
Without depending on convertible, you could just define a conversion function either from Int to D (and write a == fromInt 2) or vice versa.
A less recommended route (for this specific case I think it's simply worse than the first solution) would be to define your own type class, e.g.
class Eq' a b where
(=~=) :: a -> b -> Bool
instance Eq a => Eq' a a where
x =~= y = x == y
instance Eq' D Int where ...
etc.
This can be done, but I doubt you will want to do this. As Alexey mentioned the type of (==) is Eq a=>a->a->Bool, so the only way to make this work would be to make 2 have type D. This may seem absurd at first, but in fact numbers can be made to have any type you want, as long as that type is an instance of Num
instance Num D where
fromInteger x = C x 1.0
There are still many things to work out, though....
First, you need to fully implement all the functions in Num, including (+), (*), abs, signum, fromInteger, and (negate | (-)).
Ugh!
Second, you have that extra Float to fill in in fromInteger. I chose the value 1.0 above, but that was arbitrary.
Third, you need to actually make D an instance of Eq also, to fill in the actual (==).
instance Eq D where
(C x _) == (C y _) = x == y
Note that this is also pretty arbitrary, as I needed to ignore the Float values to get (==) to do what you want it to.
Bottom line is, this would do what you want it to do, but at the cost of abusing the Num type, and the Eq type pretty badly.... The Num type should be reserved for things that you actually would think of as a number, and the Eq type should be reserved for a comparison of two full objects, each part included.

Why it is impossible to divide Integer number in Haskell?

This code
(4 :: Integer) / 2
will lead to error:
No instance for (Fractional Integer) arising from a use of ‘/’
In the expression: (4 :: Integer) / 2
In an equation for ‘it’: it = (4 :: Integer) / 2
Why?
I need to specify
fromIntegral(4 :: Integer) / 2
to get a result. But what if I need a real number and not 2.0?
Because the Integer type has no Fractional instance.
The type for (/) is Fractional a => a -> a -> a. Consider what happens when a = Integer. You'd have Integer -> Integer -> Integer. But 1/2 is not an integer, it's 0.5. So the only way to fit the division operator would be to round the result. But there is not a single way to round, and the best choice depends on the application, hence it was decided to not provide that instance.
If you want to perform integer division use the div or quot functions (they use different rounding).
Otherwise convert to something that supports a well-defined division operation like Rational (this is what the fromIntegral is doing).
Because the division operator for integers has two results (quotient and remainder):
divMod :: Integer -> Integer -> (Integer, Integer)
You can also use the div operator:
n `div` m
which returns only one component of the division result (the quotient), but that's not the same thing as n / m. / is for types where the division operator has only one result which combines 'quotient' and 'remainder' in one fraction.
Equationally, if (q, r) = n `divMod` m, then
n = m * q + r
whereas if q = x / y, then
x = y * q
(up to the usual caveats about floating point numbers and approximations).
Substituting div for / breaks that relationship, because it throws away some of the information you need to reproduce n.
In Haskell, the class Fractional contains all types which are capable of division. Indeed, this is how division is defined; accordingly, whenever Haskell encounters /, it looks for an instance of Fractional for the type being operated on. Because there is no instance of the class Fractional for Integer, Haskell does not have a definition for / on Integer.
Haskell has several subclasses of the Num class, and they are worth being familiar with in order to type your classes in the most appropriate way possible.

Haskell type family instance with type constraints

I am trying to represent expressions with type families, but I cannot seem to figure out how to write the constraints that I want, and I'm starting to feel like it's just not possible. Here is my code:
class Evaluable c where
type Return c :: *
evaluate :: c -> Return c
data Negate n = Negate n
instance (Evaluable n, Return n ~ Int) => Evaluable (Negate n) where
type Return (Negate n) = Return n
evaluate (Negate n) = negate (evaluate n)
This all compiles fine, but it doesn't express exactly what I want. In the constraints of the Negate instance of Evaluable, I say that the return type of the expression inside Negate must be an Int (with Return n ~ Int) so that I can call negate on it, but that is too restrictive. The return type actually only needs to be an instance of the Num type class which has the negate function. That way Doubles, Integers, or any other instance of Num could also be negated and not just Ints. But I can't just write
Return n ~ Num
instead because Num is a type class and Return n is a type. I also cannot put
Num (Return n)
instead because Return n is a type not a type variable.
Is what I'm trying to do even possible with Haskell? If not, should it be, or am I misunderstanding some theory behind it? I feel like Java could add a constraint like this. Let me know if this question could be clearer.
Edit: Thanks guys, the responses are helping and are getting at what I suspected. It appears that the type checker isn't able to handle what I'd like to do without UndecidableInstances, so my question is, is what I'd like to express really undecidable? It is to the Haskell compiler, but is it in general? i.e. could a constraint even exist that means "check that Return n is an instance of Num" which is decidable to a more advanced type checker?
Actually, you can do exactly what you mentioned:
{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances #-}
class Evaluable c where
type Return c :: *
evaluate :: c -> Return c
data Negate n = Negate n
instance (Evaluable n, Num (Return n)) => Evaluable (Negate n) where
type Return (Negate n) = Return n
evaluate (Negate n) = negate (evaluate n)
Return n certainly is a type, which can be an instance of a class just like Int can. Your confusion might be about what can be the argument of a constraint. The answer is "anything with the correct kind". The kind of Int is *, as is the kind of Return n. Num has kind * -> Constraint, so anything of kind * can be its argument. It perfectly legal (though vacuous) to write Num Int as a constraint, in the same way that Num (a :: *) is legal.
To complement Eric's answer, let me suggest one possible alternative: using a functional dependency instead of a type family:
class EvaluableFD r c | c -> r where
evaluate :: c -> r
data Negate n = Negate n
instance (EvaluableFD r n, Num r) => EvaluableFD r (Negate n) where
evaluate (Negate n) = negate (evaluate n)
This makes it a bit easier to talk about the result type, I think. For instance, you can write
foo :: EvaluableFD Int a => Negate a -> Int
foo x = evaluate x + 12
You can also use ConstraintKinds to apply this partially (which is why I put the arguments in that funny-looking order):
type GivesInt = EvaluableFD Int
You could do this with your class as well, but it would be more annoying:
type GivesInt x = (Evaluable x, Result x ~ Int)

Deriving Data.Complex in Haskell

I have code that looks a little like the following:
import Data.Complex
data Foo = N Number
| C ComplexNum
data Number = Int Integer
| Real Float
| Rational Rational
deriving Show
data ComplexNum = con1 (Complex Integer)
| con2 (Complex Float)
| con3 (Complex Rational)
deriving Show
But this seems like a bad way to do it. I would rather have
data Foo = N Number
| C (Complex Number)
and construct a ComplexNumber with something similar to ComplexNumber $ Real 0.0.
The question is how to make Complex Number possible. Since all of the types in Number have corresponding Complex instances, can I just add deriving Complex to Number?
The Haskell approach is to have different types for Complex Float and Complex Int rather than trying to unify them into one type. With type classes you can define all of these types at once:
data Complex a = C a a
instance Num a => Num (Complex a) where
(C x y) + (C u v) = C (x+u) (y+v)
(C x y) * (C u v) = C (x*u-y*v) (x*v+y*u)
fromInteger n = C (fromInteger n) 0
...
This at once defines Complex Int, Complex Double, Complex Rational, etc. Indeed it even defines Complex (Complex Int).
Note that this does not define how to add a Complex Int to a Complex Double. Addition (+) still has the type (+) :: a -> a -> a so you can only add a Complex Int to a Complex Int and a Complex Double to another Complex Double.
In order to add numbers of different types you have to explicitly convert them, e.g.:
addIntToComplex :: Int -> Complex Double -> Complex Double
addIntToComplex n z = z + fromIntegral n
Have a look at http://www.haskell.org/tutorial/numbers.html section 10.3 for more useful conversion functions between Haskell's numeric type classes.
Update:
In response to your comments, I would suggest focusing more on the operations and less on the types.
For example, consider this definition:
onethird = 1 / 3
This represents the generic "1/3" value in all number classes:
import Data.Ratio
main = do
putStrLn $ "as a Double: " ++ show (onethird :: Double)
putStrLn $ "as a Complex Double: " ++ show (onethird :: Complex Double)
putStrLn $ "as a Ratio Int: " ++ show (onethird :: Ratio Int)
putStrLn $ "as a Complex (Ratio Int): " ++ show (onethird :: Complex (Ratio Int))
...
In a sense Haskell let's the "user" decide what numeric type the expression should be evaluated as.
This doesn't appear to be legal Haskell code. You have three constructors of type ComplexNum all named Complex. Also, data types must begin with a capital letter, so foo isn't a valid type. It's hard to tell what you mean, but I'll take a stab:
If you have a type
data Complex a = (a,a)
you can keep your definition of Number and define foo as:
data Foo = N Number
| C (Complex Number)

Resources