I was trying to implement Integers at the type level in Haskell. To start I implemented natural numbers with
data Zero
data Succ a
I then extended this to the integers with
data NegSucc a
I decided to then create an Increment
class that would increment integers. Here is how I did that:
{-# Language FunctionalDependencies #-}
{-# Language UndecidableInstances #-}
{-# Language MultiParamTypeClasses #-}
{-# Language FlexibleInstances #-}
import Prelude ()
-- Peano Naturals --
data Zero
data Succ a
class Peano a
instance Peano Zero
instance (Peano a) => Peano (Succ a)
-- Integers --
data NegSucc a -- `NegSucc a` is -(a+1) so that 0 can only be expressed one way
class Integer a
instance (Peano a) => Integer a
instance (Peano a) => Integer (NegSucc a)
-- Arithmetic Operations --
class Increment a b | a -> b
instance (Peano a) => Increment a (Succ a)
instance Increment (NegSucc Zero) Zero
instance (Peano a) => Increment (NegSucc (Succ a)) (NegSucc a)
However when I run this GHC complains that Functional dependencies conflict between instance declarations
, and cites all three of my increment instances. This error doesn't make much sense to me, I don't see any conflict between the separate declarations. What confuses me even further is that if I change the first instance to two separate instances
instance (Peano a) => Increment (Succ a) (Succ (Succ a))
instance Increment Zero (Succ Zero)
The compiler stops complaining altogether. However the rules that define Peano a
tell me that these two things should be the same.
Why do I get a functional dependency conflict when I write the single line version but none when I write the two line version?
NegSucc (NegSucc Zero)
is -(-(0 + 1) + 1) = -(-1 + 1) = -0 = 0, so you have multiple representations of 0 anyway. – SpillNegSucc (NegSucc Zero)
is not anInteger
, because Integers are either peano numerals or theNegSucc
of peano numerals.NegSucc (NegSucc Zero)
cannot be incremented either since only Integers can be incremented. You might be able to argue thatNegSucc (NegSucc Zero)
is equivalent toZero
but I don't think it is very meaningful. – Beseech