# toIntegralSized

Programming involves a really upsetting amount of numbers. We are perpetually finding ourselves dealing with numbers in the sorts of programs that seemingly have no just cause to expose us to arithmetic tedium. The greatest redeeming quality of numbers is the sense of possibility conveyed by the unlimited expanse of the number line – But machines mute even this glimmer of hope, offering instead a dim and claustrophobic view.

Here’s the thing: We treat our numbers in a most cruel manner, packing them into dark corners, shoving them through nanoscopically thin wires. They live in tiny boxes, because in computing, small is fast. And under these conditions, our numbers cannot handle much stress before they start bouncing off the walls.

Try starting with an `Int64` of 100 and repeatedly square it. You won’t get far.See Introduction to GHCi for a discussion of `it`.

``````λ> import Data.Int

λ> 100 :: Int64
100

λ> it ^ 2
10000

λ> it ^ 2
100000000

λ> it ^ 2
10000000000000000

λ> it ^ 2
-8814407033341083648``````

`Int64` is not a type for unbounded possibilities, not a realm in which to explore the vast glory of mathematics. `Int64` offers efficient and uninspiring service for tasks such as… counting.

``````λ> 1 :: Int64
1

λ> it + 1
2

λ> it + 1
3

λ> it + 1
4

λ> it + 1
5``````

For this sort of thing, `Int64` will pretty much stay in its lane. It takes a while to plus-one your way out of an `Int64` box.

We do have an unbounded type! It’s called `Integer`.Mnemonic: The type with the longer name can hold bigger numbers. Just as ‘Int’ is an abbrevation for ‘Integer’, types with ‘Int’ in their names are “abbreviated” notions of integerness. The `Integer` type will neither give you up nor let you down.

``````λ> 100 :: Integer
100

λ> it ^ 2
10000

λ> it ^ 2
100000000

λ> it ^ 2
10000000000000000

λ> it ^ 2
10000000000000000000000000
0000000

λ> it ^ 2
10000000000000000000000000
00000000000000000000000000
0000000000000

λ> it ^ 2
10000000000000000000000000
00000000000000000000000000
00000000000000000000000000
00000000000000000000000000
0000000000000000000000000``````

It’s so nice, it makes you want to move to Integer Land, buy a little house there, plant some fruit trees, spend your evenings on the porch with a glass of wine looking out over the –

Snap out of it, you’re daydreaming! You’re not going to get Integers all the time, it’s just not realistic. In fact, it’s only going to get worse.

Do you know what the upper bound on `Int64` is? We said it was small, but that’s only in comparison to infinity. Really, it’s kind of an absurdly high number.

``````λ> maxBound :: Int64
9223372036854775807``````

A lot of situations that call for a number are situations where we know that the number won’t be nearly that high. Say you’ve got a cheap digital room thermometer that reports temperatures in whole degrees Fahrenheit. Maybe it’s going to give you an `Int16`. That’s way smaller than `Int64`, but this bad boy can still fit so many temperatures.

``````λ> minBound :: Int16
-32768

λ> maxBound :: Int16
32767``````

Programmers, hardware builders, network protocol designers – they’re all going to give you numbers, and they’re all going to require numbers from you. And here’s the snag: Because everybody is putting their numbers into the smallest box they can get away with, and because how small a box you can get away with depends on exactly what you’re doing, sooner or later you’re going to end up with a square peg and a round hole.

“We gotta find a way to make this fit into the hole for this” – from Apollo 13 (1995)

It is astonishing how casually we often see numbers abused as they are shoved from one box to another. The `fromIntegral` function in the `Prelude` module is one example of how numbers can get hurt.

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

This is an extremely polymorphic function – Both its input and output are type variables. So we’re going to need some type annotations in our demonstration, to ensure that the compiler knows what types we’re converting to and from.

Here’s how it works on a good day:

``````λ> fromIntegral (1243 :: Int64) :: Int16
1243``````

A number goes in, the same number comes out in new clothes as a different type. But what happens when the number doesn’t fit into its new clothes? Nothing good, I’ll tell you.

``````λ> fromIntegral (475891 :: Int64) :: Int16
17139

λ> fromIntegral (-1243 :: Int64) :: Word64
18446744073709550373``````

Don’t treat your numbers like this!

Generally the best tool for this kind of work is a function called `toIntegralSized`.

``````toIntegralSized ::
( Integral a, Bits a,
Integral b, Bits b ) =>
a -> Maybe b``````

This function comes from a rather obscure place at the bottom of the `Data.Bits` module in the `base` package. You can also find it in the `relude` package, where it is included in the `Relude` module and featured more prominently in the `Relude.Numeric` module.

``````λ> toIntegralSized (1243 :: Int64) :: Maybe Int16
Just 1243

λ> toIntegralSized (475891 :: Int64) :: Maybe Int16
Nothing``````

The output type is `Maybe` because a reasonable conversion from one type of number to another is not always possible, owing to each type’s different boundaries. As the example above illustrates, if an `Int64` value is too large, an attempt to transfer it into a smaller `Int16` box may yield `Nothing`.

Likewise, a negative integer will fail to convert to any “word” type; such things are only for non-negative numbers.

``````λ> import Data.Word

λ> toIntegralSized (1243 :: Int64) :: Maybe Word64
Just 1243

λ> toIntegralSized (-1243 :: Int64) :: Maybe Word64
Nothing``````

With `toIntegralSized` at your disposal, you can confidently tackle those pesky integer conversion tasks and shift your numbers around into whatever format is required of them. It doesn’t remove all your need to think, because you still have that `Nothing` possibility to deal with, but you have an extremely versatile conversion function that never produces erroneous off-the-wall results.

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.