For example, one bad way is to factor through a string:
toReadableNum :: (Num a, Num b, Read b) => a -> b
toReadableNum = read . show
If there are no good ways, are there other bad ways? Implementation specific? Requiring language extension?
You can't go (sanely) from Num
to Num
, as Num provides no mechanism for extracting information about the value held other than its spurious Eq and Show machinery, but if you are willing to assume a bit more on the behalf of the number you are coming from, then you can have recourse.
In particular
fromIntegral :: (Integral a, Num b) => a -> b
and the composition of
toRational :: Real a => a -> Rational
with
fromRational :: Fractional a => Rational -> a
are both good candidates for doing what you mean, if not exactly what you asked for.
While read . show
is well typed and has the signature you propose, the meaning is gobbledigook. There is nothing at all that says the text emitted by one Show
instance will be compatible with a completely different Read
instance, and there are plenty of counter examples.
The (implied) contract on Read
and Show
only apply when you use them with the same type!
There are no good ways. Some numbers contain more information that other, so how could you expect to convert between two arbitrary numbers in a good way. Some simple examples: How do you convert a Double to an Int? A Rational to on Int8? A Complex Double to a Float?
All this involve information loss and then there is no obvious right way.
And as @hammar says, the operations in Num
simply don't allow you to construct such a function.
You cannot write any useful function of the type (Num a, Num b) => a -> b
. Since a
and b
are type variables, the only useful operations we can use on them are the ones in the Num
class. (Eq
and Show
won't help us much here).
class (Eq a, Show a) => Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
The only function here that allows you to make an b
if you didn't have one to start with is fromInteger
, but you have no way of turning a
into an Integer
, so the only functions you can write of this type return fromInteger
of some constant, or bottom. Not very useful.
As augustss pointed out, there is no obvious way of making this conversion anyway. Remember lots of types can be Num
. Not only the various types of real numbers, but also complex numbers, matrices, polynomials, etc. There is no meaningful conversion that would work between all of them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With