例如,一种不好的方法是通过字符串:
toReadableNum :: (Num a, Num b, Read b) => a -> b
toReadableNum = read . show
如果没有好方法,还有其他不好的方法吗?具体实施?需要语言扩展吗?
答案 0 :(得分:7)
没有好办法。有些数字包含更多其他数据,所以你怎么能期望以一种好的方式在两个任意数字之间进行转换。一些简单的例子:如何将Double转换为Int?对Int8有理由吗?一个复杂的双重浮动?
所有这些都涉及信息丢失,然后没有明显的正确方法。
正如@hammar所说,Num
中的操作根本不允许你构造这样的函数。
答案 1 :(得分:7)
你不能(明智地)从Num
到Num
,因为Num没有提供任何机制来提取除了它的虚假Eq和Show机器之外的值,但是如果你愿意的话代表您来自的号码,假设更多,那么您可以追索。
特别是
fromIntegral :: (Integral a, Num b) => a -> b
和
的组成toRational :: Real a => a -> Rational
与
fromRational :: Fractional a => Rational -> a
如果不是你要求的话,都是做你意思的好人选。
虽然read . show
输入得很好且有你提出的签名,但意思是gobbledigook。没有什么可以说一个Show
实例发出的文本将与完全不同的Read
实例兼容,并且有很多反例。
Read
和Show
上的(隐含)合同仅适用于您使用相同类型的合同!
答案 2 :(得分:3)
您无法编写(Num a, Num b) => a -> b
类型的任何有用功能。由于a
和b
是类型变量,因此我们可以在其上使用的唯一有用的操作是Num
类中的操作。 (Eq
和Show
在这里对我们没什么帮助。)
class (Eq a, Show a) => Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
此处唯一允许您制作b
的功能,如果您没有fromInteger
,a
,则无法将Integer
转换为fromInteger
{1}},因此您可以编写此类型的唯一函数返回某个常量或底部的Num
。不太有用。
作为augustss pointed out,无论如何都没有明显的方法进行此转换。请记住,许多类型可以是{{1}}。不仅是各种类型的实数,还有复数,矩阵,多项式等。没有任何有意义的转换可以在所有实数之间起作用。
答案 3 :(得分:0)
好方法是进行特定类型的转换,例如圆形或钳形。这样的功能就像它所说的那样。