Search code examples
haskellboolean

How does Haskell avoid never-ending recursion in boolean value definitions?


Years ago I read about how Haskell compares boolean expressions and I wanted to see if I can use the same concept in my project (F#), but I don't understand how it works:

Source: https://hackage.haskell.org/package/ghc-prim-0.10.0/docs/src/GHC.Classes.html#%3D%3D

x /= y               = not (x == y)
x == y               = not (x /= y) 

It makes perfect sense, but how doesn't it end in a never-ending recursion?


Context: in my project I have spent and unspent coins and I think they could be handled similar to booleans, where a coin is unspent when it is not spent and it is spent when it is not unspent.


Solution

  • It makes perfect sense, but how doesn't it end in a never-ending recursion?

    This is a typeclass, the instances should make an implementation. What you see is a default (fallback) implementation.

    The compiler will normally enforce this, indeed. The class does not only provide function signatures, and default implementations, but shows:

    class Eq a where
      -- …
      {-# MINIMAL (==) | (/=) #-}

    the minimal means that the instances of the typeclass will either have to implement (==) or (/=) (they can of course implement both).

    This is also the case for any sensical instance of Eq, indeed, for example with Int:

    instance Eq Int where
        (==) = eqInt
        (/=) = neInt
    

    where eqInt and neInt in this case are implemented as:

    eqInt, neInt :: Int -> Int -> Bool
    (I# x) `eqInt` (I# y) = isTrue# (x ==# y)
    (I# x) `neInt` (I# y) = isTrue# (x /=# y)
    

    These then have ==# functions that work on unboxed Int# values.

    Beware that a class in Haskell is a typeclass, this looks more like what one would see as an interface in object-oriented programming. It does not deal with (concrete) data, it just provides an interface that should be implemented.