Haskell has a good way to write a conversion function num to num: toNum :: (Num a, Num b) => a & # 8594; b`?

For example, one bad way is to express 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? Need a language extension?

+6
source share
4 answers

You cannot go (safely) from Num to Num , since Num does not provide a mechanism for extracting information about a value other than its false equalizer and show mechanisms, but if you are willing to accept a little more from the name of the number you came from, then you can ask for help.

In particular,

 fromIntegral :: (Integral a, Num b) => a -> b 

and composition

 toRational :: Real a => a -> Rational 

from

 fromRational :: Fractional a => Rational -> a 

are good candidates for what you mean, if not quite what you requested.

Bye read . show read . show well-typed and has the signature you are proposing, the value is gobbledigook. There is nothing that says that the text emitted by one instance of Show will be compatible with a completely different instance of Read , and there are many examples of counter examples.

The (implied) Read and Show contract applies only when used with the same type!

+7
source

There are no good ways. Some numbers contain more information about others, since you can count on converting between two arbitrary numbers in a good way. Some simple examples: how do you convert Double to Int? Rational for Int8? Integrated double floating?

All this is associated with the loss of information, and then there is no obvious right way.


And as @hammar says, operations in Num just don't let you build such a function.

+7
source

You cannot write any useful function like (Num a, Num b) => a -> b . Since a and b are type variables, the only useful operations we can use on them are those contained in the Num class. ( Eq and Show will not help 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 that allows you to do b if you did not have this is fromInteger , but you cannot turn a into Integer , so the only function you can write this type return fromInteger some constant or bottom. Not very helpful.


As augustss pointed out , there is no obvious way to do this conversion anyway. Remember that many types can be Num . Not only various types of real numbers, but also complex numbers, matrices, polynomials, etc. There is no meaningful transformation that could work between all of them.

+3
source

A good way is to make a certain type of conversion, for example, round or clamp. Such a function does what it says.

0
source

Source: https://habr.com/ru/post/893398/


All Articles