Skip to content

Instantly share code, notes, and snippets.

@munro
Created August 22, 2014 20:38
Show Gist options
  • Save munro/16faff2cedef2fa4ac37 to your computer and use it in GitHub Desktop.
Save munro/16faff2cedef2fa4ac37 to your computer and use it in GitHub Desktop.
Integer addition in Haskell without built in functions
data MyInteger = Zero MyInteger | One MyInteger | End
-- | Show integer
-- >>> show (One $ One $ Zero $ Zero $ Zero $ End)
-- "11000b"
-- >>> show (End)
-- "b"
instance Show MyInteger where
show (Zero rest) = "0" ++ show rest
show (One rest) = "1" ++ show rest
show (End) = "b"
-- | Flip a number so we can add from the right side
-- >>> flipBinary (One $ Zero $ End)
-- 01b
-- >>> flipBinary (One $ One $ Zero $ End)
-- 011b
-- >>> flipBinary (One $ One $ Zero $ Zero $ Zero $ End)
-- 00011b
-- >>> flipBinary (One $ Zero $ Zero $ End)
-- 001b
flipBinary :: MyInteger -> MyInteger
flipBinary num = flipBinaryCarry num End
flipBinaryCarry :: MyInteger -> MyInteger -> MyInteger
flipBinaryCarry (One rest) carry = flipBinaryCarry rest (One $ carry)
flipBinaryCarry (Zero rest) carry = flipBinaryCarry rest (Zero $ carry)
flipBinaryCarry (End) carry = carry
-- | Add two integers together
-- >>> addition (One $ End) (One $ End)
-- 10b
-- >>> addition (One $ Zero $ Zero $ End) (One $ Zero $ Zero $ End)
-- 1000b
-- >>> addition (One $ One $ One $ End) (One $ One $ One $ One $ End)
-- 10110b
-- >>> addition (One $ One $ One $ One $ End) (One $ One $ One $ One $ End)
-- 11110b
addition :: MyInteger -> MyInteger -> MyInteger
addition a b = flipBinary $ additionCarry (flipBinary a) (flipBinary b) False
additionCarry :: MyInteger -> MyInteger -> Bool -> MyInteger
additionCarry (One rest_a) (One rest_b) True = One $ additionCarry rest_a rest_b True
additionCarry (One rest_a) (Zero rest_b) True = Zero $ additionCarry rest_a rest_b True
additionCarry (Zero rest_a) (One rest_b) True = Zero $ additionCarry rest_a rest_b True
additionCarry (Zero rest_a) (Zero rest_b) True = One $ additionCarry rest_a rest_b False
additionCarry (One rest_a) (One rest_b) False = Zero $ additionCarry rest_a rest_b True
additionCarry (One rest_a) (Zero rest_b) False = One $ additionCarry rest_a rest_b False
additionCarry (Zero rest_a) (One rest_b) False = One $ additionCarry rest_a rest_b False
additionCarry (Zero rest_a) (Zero rest_b) False = Zero $ additionCarry rest_a rest_b False
additionCarry (One rest) (End) True = Zero $ additionCarry rest End True
additionCarry (Zero rest) (End) True = One $ additionCarry rest End False
additionCarry (One rest) (End) False = One $ additionCarry rest End False
additionCarry (Zero rest) (End) False = Zero $ additionCarry rest End False
additionCarry (End) (One rest) True = Zero $ additionCarry rest End True
additionCarry (End) (Zero rest) True = One $ additionCarry rest End False
additionCarry (End) (One rest) False = One $ additionCarry rest End False
additionCarry (End) (Zero rest) False = Zero $ additionCarry rest End False
additionCarry (End) (End) True = One End
additionCarry (End) (End) False = End
main :: IO ()
main = do
putStrLn $ show (One $ Zero $ Zero $ End)
putStrLn $ show $ addition (One $ Zero $ Zero $ End) (One $ End)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment