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
.