Hello folks, I have the following code, and I am having trouble understanding how fromIntegral is functioning:
avgDb :: [DatabaseItem] -> Double
avgDb dataBase = dividend / divisor
where dividend = fromIntegral $ sumDb dataBase
divisor = fromIntegral $ length $ filterDbNumber dataBase
Note that sumDb :: [DatabaseItem] -> Integer and filterDbNumber :: [DatabaseItem] -> [Integer].
I understand that the (/) :: Fractional a => a -> a -> a. In other words, the / operator must be applied to two values whose type has an instance of Fractional.
By looking at the output of :i Fractional in GHCi, I see that in order to define an instance of Fractional for a type, that type must already define an instance of Num. I also see that DiffTime, NominalDiffTime, Float, and Double are the types that the system knows implement Fractional.
The type signature of fromIntegral is fromIntegral :: (Num b, Integral a) => a -> b. So, I can apply fromIntegral to any values whose type has an instance of Integral.
From the output of :i Integral, I can tell that the types Word, Integer and Int all have instances of Integral.
Despite all of this information, I still can't get a consistent mental model. I am applying the function fromIntegral to two values of type Integer. What is fromIntegral returning? Is it basically striping the Integer values of their concrete data types, and returning values that have no concrete data type, but a typeclass constraint of Num? Therefore, when I apply the / operator to these values with no conrete data type, / is able to apply a concrete data type to them. Given the type signature of sumDb, GHCi can infer that the arguments to / must be Double.