# Why are these two haskell functions not equivalent?

I looked at these functions:

```
import Data.Digits (digits)
numberDivider (a,b) = a / b
numberDivider2 (num,denom) = num / denom
where
a = head $ digits 10 num
b = head . tail $ digits 10 denom
```

We can look at the types of these functions:

```
λ> :t numberDivider2
numberDivider2 :: (Integral a, Fractional a) => (a, a) -> a
λ> :t numberDivider
numberDivider :: Fractional a => (a, a) -> a
```

`numberDivider`

does what you think. `numberDivider2`

gives:

```
No instance for (Show a0) arising from a use of ‘print’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Show Double -- Defined in ‘GHC.Float’
instance Show Float -- Defined in ‘GHC.Float’
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 34 others
In a stmt of an interactive GHCi command: print it
```

when called with correct arguments (e.g. (48,98)). Now I can't see how to do something more specific leads to ambiguity? I feel like I'm so stupid. (I also don't understand why the function has to come from `(a,a) -> a`

, as I would have thought it would be `(a,a) -> b`

where a is `Integral`

and b is a float or something.

I tried to insert type annotations to force it to use Float for the result.

Can anyone point out what I am missing here?

source to share

This most likely comes from the definition `digits`

, which I assume it takes `Integrala => a`

as one of its arguments. This place then adds an additional constraint `Integral`

to the argument `numberDivider2`

. As it turns out, there is not a type that is an instance of how `Fractional`

, and so `Integral`

. When entering numeric literals, however, it tries to convert from `Num a => a`

to `(Integral a, Fractional a) => a`

, and there are special rules in GHCi to try to find an instance that also uses `Show`

so that you can print it to the screen. Since no such type exists, you get an error.

Now the real problem seems to come from a misunderstanding of the Haskell numbering system. You cannot use `/`

for all numbers, for example `Int`

s, because it is `/`

not defined for these types. You can only use it `/`

for fractional types, hence the class `Fractional`

. If you want to convert `Int`

or `Integer`

to `Float`

, or `Double`

for the performance of the division with a floating point, you can use `fromIntegral`

to convert them into any type `Num`

, ~~the eg~~

```
a = head $ digits 10 $ fromIntegral num
b = head . tail $ digits 10 $ fromIntegral denom
```

This should remove the constraint `Integral`

from the function.

Looking at the type `digits`

, I can see that it doesn't work. Instead, you probably want something like

```
numberDivider2 :: (Integral a, Fractional b) => (a, a) -> b
numberDivider2 (num, denom) = fromIntegral num / fromIntegral denom
where
a = head $ digits 10 num
b = head . tail $ digits 10 denom
```

Pay attention to the location of the `fromIntegral`

s, they will convert each value `Integral`

where you want to perform the operation `Fractional`

.

source to share

Now I can't see how to do something more specific leads to ambiguity?

This is ambiguous in both cases, but in case of `numberDivider`

ambiguity can be resolved using Haskell's default rules. In this particular case, these rules basically say that if multiple numeric types are possible, and one of them `Integer`

, choose `Integer`

. If `Integer`

not possible, but available `Double`

, select `Double`

. If none of these are possible, uncertainty remains.

In case `numberDivider`

`Integer`

it is impossible because it is `Integer`

not an instance `Fractional`

, but `Double`

is. Therefore it is chosen `Double`

.

In case `numberDivider`

it is impossible, because there is simply no type that and `Integral`

, and `Fractional`

. Therefore, ambiguity remains.

You could argue that the set of exactly 0 possible types is not ambiguous, but simply impossible, so the error message should be different, but it should also account for instances that might be defined elsewhere. That is, although there are no types in the standard library `Fractional`

and `Integral`

they can be defined elsewhere, so we cannot rule out this possibility (although it does not make sense).

source to share