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
does what you think.
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
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
, which I assume it takes
Integrala => a
as one of its arguments. This place then adds an additional constraint
to the argument
. As it turns out, there is not a type that is an instance of how
, and so
. When entering numeric literals, however, it tries to convert from
Num a => a
(Integral a, Fractional a) => a
, and there are special rules in GHCi to try to find an instance that also uses
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
s, because it is
not defined for these types. You can only use it
for fractional types, hence the class
. If you want to convert
for the performance of the division with a floating point, you can use
to convert them into any type
a = head $ digits 10 $ fromIntegral num b = head . tail $ digits 10 $ fromIntegral denom
This should remove the constraint
from the function.
Looking at the type
, 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
s, they will convert each value
where you want to perform the operation
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
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
not possible, but available
. If none of these are possible, uncertainty remains.
it is impossible because it is
not an instance
is. Therefore it is chosen
it is impossible, because there is simply no type that and
. 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
they can be defined elsewhere, so we cannot rule out this possibility (although it does not make sense).
source to share