I have seen the following data constructor for Church numerals
data Nat = Zero | Succ Nat deriving Show
But this is unary numbers. How do we implement a data constructor for Binary numbers in Haskell in this way?
I have tried this:
data Bin = Zero | One | BinC [Bin] deriving Show
After this we can get, decimal 5 encoded as BinC [One,Zero,One]
But I think I am missing something here. My solution seems not as clever as the Church's solution. No surprise, I am not Church. Little bit of thinking, I found that my solution depends upon list, whereas the Nat doesn't depend upon any such external structure like list.
Can we write a solution that is similar to Church's using a Succ type constructor for Binary numbers too? If yes, how? I tried a lot, but it seems my brain cannot get rid of the need of list or some other such structure.
The closest I can think of would be something like
This makes it possible to construct binary numbers doing just
One could also imagine a decoding function working on the principle of (much better version suggested by Ingo in the comments)
Which can then be used to decode a binary number to an integral number.
The difficulty with what you want to accomplish is that you need to read binary numbers "inside out" or so to speak. To know the value of the most significant digit, you need to know how many digits you have in the number. If you were to write your binary numbers in "reverse" – i.e. the outermost digit is the least significant digit, then things would be a lot easier to handle but the numbers would look backwards when you create them and print them out using the default instance of
Show
.The reason this is not a problem with unary numbers is because there is no "least significant digit" since all digits have the same value, so you can parse the number from either direction and you will get the same result.
For completeness, here is the same thing but with the outermost digit being the least significant digit:
That looks pretty much like before, but you'll notice that when the decoding function is implemented,
Numbers are written backwards!
However, this is a lot easier to handle. We can for example add two binary numbers on a case-by-case basis. (Warning: lots of cases!)
At which point adding two binary numbers is a breeze:
And indeed!