# [Haskell-cafe] Newbie Q: Deriving MyOrd from Eq problem

voigt.16734551 at bloglines.com voigt.16734551 at bloglines.com
Wed Jul 26 11:24:15 EDT 2006

```Hi Dmitri,

I don't have answers for all your questions. But some, at least.

--- Dmitri O.Kondratiev" <dokondr at gmail.com wrote:
> -- Ok,  then I can
derive MyOrd class directly from Ord:
>
> class Ord a => MyOrd a where

> 	(%<), (%<=), (%>), (%>=) :: a -> a -> Bool
> 	x %< y = x < y
> 	x %<=
y = (x < y || x == y)
> 	x %> y =  y < x
> 	x %>= y = (y < x || x == y)

>
> instance (MyOrd a, MyOrd b) => MyOrd (a,b) where
> 	(x1, y1) %< (x2,
y2) = (x1 %< x2) && (y1 %< y2)
> 	(x1, y1) %> (x2, y2) = (x1 %> x2) && (y1
%> y2)
> 	(x1, y1) %<= (x2, y2) = (x1 %<= x2) && (y1 %<= y2)
> 	(x1, y1)
%>= (x2, y2) = (x1 %>= x2) && (y1 %>= y2)
>
> greaterMyOrd :: (MyOrd (a,
b)) => (a, b) -> (a, b) -> Bool
> greaterMyOrd (x,y) (z,t) = (x,y) %> (z,t)

>
> -- This should work, right? Yet I get this error message:

Only if
you tell the compiler to allow constraints of the form (C t), where C is a
class and t is not a variable. That's exactly what GHC tells you to try, using
-fglasgow-exts.

> -- Notwithstanding :) when i comment out declaration:

>
> -- greaterMyOrd :: (MyOrd (a, b)) => (a, b) -> (a, b) -> Bool
>
> -- program gets compiled and checking type of  'greaterMyOrd' gives:
>

> *ClassTest> :t greaterMyOrd
> greaterMyOrd :: (MyOrd (a, b)) => (a, b)
-> (a, b) -> Bool
>
> -- which is the same as I tried to declare in the
program source.
> What is hapenning here?

That is indeed a bit funny.
Using your instance declaration, GHC could have reduced the constraint "MyOrd
(a,b)" to "MyOrd a, MyOrd b". I think there was a discussion on why it does
not do so very recently. Maybe you can find it in the archive.

> -- Now,
when trying to use function 'greaterMyOrd' I get:
>
> *ClassTest> greaterMyOrd
(2, 3) (1, 2)
>
> <interactive>:1:0:
>     Ambiguous type variable `a'
in the constraints:
>       `MyOrd a' arising from use of `greaterMyOrd'
at <interactive>:1:0-11
>       `Num a' arising from the literal `2' at <interactive>:1:14

>     Probable fix: add a type signature that fixes these type variable(s)

That is because GHC doesn't know which type your literal 2 comes from.
So it doesn't know whether there is a MyOrd instance for it, or which to choose.
The Num comment comes from GHC only knowing that literal 2 will be of some
type in the Num class. But that doesn't tell it anything about possible MyOrd
instances.

> -- Then I try to declare argument types explicitely and get
this:
>
> *ClassTest> greaterMyOrd (2::MyOrd, 3::MyOrd) (1::MyOrd, 2::MyOrd)

>
> <interactive>:1:17:
>     Class `MyOrd' used as a type
>     In an
expression type signature: MyOrd
>     In the expression: 2 :: MyOrd
>
In the first argument of `greaterMyOrd', namely `(2 :: MyOrd, 3 :: MyOrd)'

> *ClassTest>

Well, just as GHC tells you, you should use a type for the
signature, not a typeclass. Try something like greaterMyOrd (2::Int, 3::Int)
(1::Int,2::Int). Maybe the annotations on the first tuple suffice.

> --
I am lost. Please enlight me, what am I doing wrong trying to
> create my
own class, its instance and then using it.

Hope that helped.

BTW, you
might get problems with overlapping instances. Because with your instance
declaration there are two possible ways, for example, to get a MyOrd instance
for (Int,Int). The first is via:

Ord Int => MyOrd Int => MyOrd (Int,Int)

The second is via:

Ord Int => Ord (Int,Int) => MyOrd (Int,Int)

Ciao,

Janis.

```