Created
August 22, 2014 20:38
-
-
Save munro/16faff2cedef2fa4ac37 to your computer and use it in GitHub Desktop.
Integer addition in Haskell without built in functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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