
On Fri, Feb 29, 2008 at 7:09 PM, Lloyd Smith
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