Home > Enterprise >  What does the fromIntegral type here actually do?
What does the fromIntegral type here actually do?

Time:12-03

I just want to clear my doubts on the fromIntegral type in Haskell.

The output for these 2 euclidean distance functions are the same, so what's the point of putting fromIntegral? Like they both give floating point values of the euclidean distances.

Also, for the type definition of my function distance2 which uses the fromIntegral type, why is it (Floating a1, Integral a2) and then => (a2, a2) -> (a2, a2) -> a1? I just don't quite get the interpretation of it here.

distance2 :: (Floating a1, Integral a2) => (a2, a2) -> (a2, a2) -> a1
distance2 (x1, y1) (x2, y2) 
      = sqrt (fromIntegral ((x2-x1)^2   (y2 - y1)^2))

distance3 :: Floating a => (a, a) -> (a, a) -> a
distance3 (x1, y1) (x2, y2) 
      = sqrt ((x2-x1)^2   (y2 - y1)^2)

Could someone please help with an explanation, thank you :)

CodePudding user response:

The output for these 2 euclidean distance functions are the same, so what's the point of putting fromIntegral? Like they both give floating point values of the euclidean distances.

They both give floating point values, but they don't both take floating point values.

> distance3 (pi, 0) (0, 0)
3.141592653589793
> distance2 (pi, 0) (0, 0)
<interactive>:2:1: error:
    • Could not deduce (Integral a20) arising from a use of ‘distance2’
      from the context: Floating a1
        bound by the inferred type of it :: Floating a1 => a1
<snipped considerable additional error text>

Also, for the type definition of my function distance2 which uses the fromIntegral type, why is it (Floating a1, Integral a2) and then => (a2, a2) -> (a2, a2) -> a1?

Your distance2 function takes numbers, and returns numbers, but not the same type of numbers. The incoming numbers must be integer-like things, so that you can apply fromIntegral to them; but the outgoing numbers must be floating-point-like things, so that you can apply sqrt to them. For example, here are some monomorphic types that distance2 can be specialized to:

(Int, Int) -> (Int, Int) -> Double
(Integer, Integer) -> (Integer, Integer) -> Double
(Word, Word) -> (Word, Word) -> Float

This English description is captured by creating two type variables, each with different constraints. An identical type for distance2, but with somewhat more human-readable variable names, might look like this:

(Floating float, Integral int) => (int, int) -> (int, int) -> float

CodePudding user response:

fromIntegral is used to convert the value of type Integral a => a that your sum-of-squares produces into a value of type Floating a => a that sqrt expects.

fromIntegral has type (Integral a, Num b) => a -> b. That means that, given a value of type Integral a, it will give you back a value of any type b that has a Num instance. Since Floating has Num as a superclass (by way of Fractional), that means fromIntegral can produce a value of type Floating a => a.

CodePudding user response:

There are two relevant typeclasses here:

  • Integral is the typeclass for types representing a subset of integers
    • each Integral type has a function toInteger that converts its values to the arbitrary-length integer type Integer
  • Num is the typeclass for numeric types that include integers as a subset
    • each Num type has a function fromInteger that converts arbitrary-length Integer values to values of that Num type

The prelude function fromIntegral is defined as:

fromIntegral = fromInteger . toInteger

It uses both of those functions to convert any Integral type to any Num type.

This is what lets your first function take any Integral type as input: the input type is inferred through the sum-of-squared-differences expression as the input to fromIntegral, and selects toInteger from that type's instance of Integral, while the Floating output type is inferred through the sqrt function to demand it as a result from the fromIntegral call, and selects the fromInteger from the output type's Num instance.

  • Related