# Haunted by PI - changing a number's base in Haskell

May 15, 2007 in

I was looking back at Christoph's ruby code and was thinking that by now I should be able to implement that algorithm in Haskell. Indeed, one of my solutions looks like that:

``````out x
| x >= base = foldl (++) [] \$ map (\f -> out \$ f x base) [mod,div]
| x < base = digit
where
range = ['a'..'z']
digit = [range!!(fromIntegral x)]
base = fromIntegral \$ length range``````

The digit to be output is a letter of the alphabet, so we are changing PI to a base 26 number system. Let's check it briefly: The map function maps one array to another. In this case the array consists of two functions, mod and div. mod returns the remainder of a division while div returns how often the divisor fits in the dividend.

In other words, the right-hand side of the dollar-sign (which is a symbol in Haskell to influence the binding power of functions and often simply aids in removing the need to put an expression in brackets) returns an array like `[out(mod x base),out(div x base)]`. foldl then gobbles it all up coming from the left. It kicks off with an empty array ([]), takes the first element and concatenates it (++) to said array, then takes the second element in the array and (++) it to what it already has, and...you get it. Btw, !! is the indexer operation to an array [1,2]!!1 gives us 2.

You may be wondering about two things:

1. What is this fromIntegral stuff?
2. Isn't the number that comes out backwards?

To the first: fromIntegral's type is

``````Main> :t fromIntegral
fromIntegral :: (Num b, Integral a) => a -> b``````

It's input is therefore an Integral. An integral, on the other hand, is an integer with "infinite" length. Yeah! I finally stumbled across a language that can do looong integers out-of-the-box.

Hence, using fromIntegral in that context gives the following signature for the function:

``````Main> :t out
out :: (Integral a) => a -> [Char]``````

It will get an arbitrary length integral and returns a String. Nice! As to the second point...Let's marry the whole thing with some IO:

``````main = do