Stuart Cook scook0 at gmail.com
Fri Feb 29 03:35:12 EST 2008

```On Fri, Feb 29, 2008 at 7:09 PM, Lloyd Smith <lloyd.g.smith at gmail.com> wrote:
>  I mixed up my types when finding the allocated and unallocated,
>  but I am not sure why it produces an error when unallocated and
>  allocated are never used? Shouldn't the two functions be compiled
>  down to the same thing?
>
>  Suggestions on how to do this more elegantly as well as pointers for
>  understanding numeric
>  type classes would be appreciated.

Let's have a look at the types involved:

Prelude> :t allocate'
allocate' :: (RealFrac a, Integral b) => a -> [a] -> [b]
Prelude> :t allocate
allocate :: (Integral b, RealFrac b) => b -> [b] -> [b]

We can see that (allocate') takes RealFrac arguments and returns an
Integral result. So far so good.

However, the signature for (allocate) is slightly different: it
requires that the argument and result types be the same.
Unfortunately, this is impossible, because no type can have a sensible
instance for both RealFrac and Integral.

Why do the two functions have different signatures? The obvious
culprit is the "unused" code in the definition of (allocate'). Notice
that (allocated) will use the same underlying type as (vs), which is
the "return" type of the function. However, unallocated tries to
subtract (allocated) from (n), and (n) has the "argument" type of the
function. The type-checker sees the two types must be the same in
order for the subtraction to work, and so the overall function ends up
with a nonsense type.

The moral of the story is that even though that extra code might not
execute at run-time, it can still influence type-inference and
type-checking, which is your actual problem here.

The solution for your woes is probably to insert a (fromIntegral)
somewhere. I suspect that

allocated = fromIntegral \$ sum vs

will do the trick.

Hope this helps,

Stuart
```