Abs from Num for Int8 uses (>) from Ord but Num specified without Ord. Why and How?

hi guys. As I know if we have type class A with a function f

class A a where
  f :: a -> a -> a

and a type class B with a function g that uses f under the hood

class B b where
  g :: b -> b -> b
  g = f

we can’t use f here, since we just don’t have an access to f, thus,
we have to add constraint, right? Right!

class A b => B b where
  g :: b -> b -> b
  g = f

Then why Int8 implementation for Num uses function from Ord type class if the Num doesn’t specify anywhere that we are using Ord?

instance Num Int8 where
...
abs x | x >= 0         = x
      | otherwise      = negate x
...

I would understand if abs was written like

abs n = if n `geInt8#` 0 then n else negate n

The same I see for Enum

...
toEnum i@(I# i#)
        | i >= fromIntegral (minBound::Int8) && i <= fromIntegral (maxBound::Int8)
                        = I8# (intToInt8# I#)
...

Can you please help me? Maybe I missed or forgot or just don’t know something. Thanks in advance!

1 Like

Remember that typeclass constraints are only necessary in polymorphic functions. The abs function is polymorphic, but its implementation for Int8 is not.

In other words: the abs function implementation for Int8 has signature Int8 -> Int8. There is no reason for a constraint to be there. It is true that using the (>) operator imposes an Ord constraint on the arguments of (>), but the Ord constraint is solved immediately. Why? Because we already know what a is: it’s an Int8.

7 Likes

wow. I need to revisit type classes. thanks!

1 Like