1
votes

I have the following code (yyyy and mm defined to be type Int):

partOne = truncate  ((fromIntegral yyyy + fromIntegral mm/100) * 1.25 + 0.97)

which on being loaded into GHCi gives me an error:

No instance for (Integral Float) arising from a use of ‘truncate’

However if I directly use the following line in GHCi, it works fine:

truncate  ((fromIntegral 2000 + fromIntegral 04/100) * 1.25 + 0.97)

There seems to be some problem related to the type Int, however I am not able to figure out how.

Also, actually I don't exactly understand what (Integral Float) means here.


For completeness's sake, the definition of the whole function is included here in case the error is caused by the whole thing instead of that single statement:

dowNumber :: Mnemonic -> PhonePad -> Date -> Float
dowNumber mn p (yyyy, mm, dd) = (partOne + partTwo) / 7 where
  partOne = (truncate  ((fromIntegral yyyy + (fromIntegral mm)/100) * 1.25 + 0.97))
  partTwo = fromIntegral ((monthToPhone mn p mm) + dd)

Mnemonic is just String and PhonePad is [(Char, Int)]. Date is (Int, Int, Int).

1
Note: StackOverflow's markdown variant doesn't know fenced code blocks, you need to use indentation.Zeta

1 Answers

3
votes

Well, truncate has type (RealFrac a, Integral b) => a -> b, which means that its polymorphic result needs to fulfil the Integral constraint. However, dowNumber's type indicates that (partOne + partTwo) / 7 is a Float. Therefore, partOne and partTwo also need to be Floats.

That would be possible if a Float was some kind of integral type. But it isn't. But to get a float from an Integral, all that's missing is another fromIntegral, either at partOne:

partOne = fromIntegral $ truncate $ …

or before you try to divide:

dowNumber … = fromIntegral (partOne + partTwo) / 7 where 
   …

How can I fix errors like this easier?

Annotate the types. In this specific case, GHC complained about truncate, and therefore about partOne. Lets simplify your example for a minute:

number :: Float
number = (a + b) / 2 where
  a = truncate $ fromIntegral 5 / 2 
  b = fromIntegral $ 12

This creates the same error as your previous program:

SO.hs:3:7:
    No instance for (Integral Float) arising from a use of ‘truncate’
    In the expression: truncate
    In the expression: truncate $ fromIntegral 5 / 2
    In an equation for ‘a’: a = truncate $ fromIntegral 5 / 2

So, the equation for a isn't correct? Lets fix the types of both a and b:

number :: Float
number = (a + b) / 2 where
  a, b :: Int
  a = truncate $ fromIntegral 5 / 2 
  b = fromIntegral $ 12

And now it gets clear:

SO.hs:2:11:
    Couldn't match expected type ‘Float’ with actual type ‘Int’
    In the first argument of ‘(+)’, namely ‘a’
    In the first argument of ‘(/)’, namely ‘(a + b)’

SO.hs:2:15:
    Couldn't match expected type ‘Float’ with actual type ‘Int’
    In the second argument of ‘(+)’, namely ‘b’
    In the first argument of ‘(/)’, namely ‘(a + b)’
Failed, modules loaded: none.