我正在尝试将此列表[1..20]从[Integer]转换为[Int]
map fromInteger [1..20]
但是这仍然给我一个整数列表
这就是它自己的转换2,它是Integer类型到Int fromInteger 2 :: Int
出了什么问题
答案 0 :(得分:7)
在Haskell中,值可以 - 就像函数一样 - 是多态的。
对于数字运算符,大多数程序员都很熟悉这个想法:没有人觉得5 + 6
有效,屈服和整数很奇怪,就像3.14159 + 2.71828
一样好,产生一个浮动。但是在像C这样的语言中,这是非常特别的,只是因为这个特殊情况非常方便。这带来了很多问题,特别是当你写1/12
之类的东西时,它会执行/
整数除法,从而产生0
。当你在中使用它时,显然不是预期的东西
for (double hourWay = 0; hourWay<1; hourWay += 1/12)
double theta = hourWay * 2 * pi;
...
所以程序员不得不诉诸丑陋的黑客,比如用小数写出分数,或明确地将其中一个数字浮动(1.0 / 12.0
,urgh!)。
Haskell为我们自动执行此操作:当它看到结果将是double(在hourWay
s声明中明确写出)时,用整数开始计算是没有意义的,因此它解释{{1并且1
立即成为浮点数。没问题,因为整数肯定形成了实数 1 的子集。您可以通过提供显式类型签名来直接访问此功能:
前奏&GT; 4 :: Int
4
前奏&GT; 4 ::双
4.0
请注意,12
不会转换号码。 :: Double
本身根本没有任何特定的类型,它是多态的:无论你想要什么数字类型,4
都是有效的描述;这在签名
前奏&GT; :t 4
4 :: Num a =&gt;一个
特别是,这意味着
前奏&GT; :t [1..20]
[1..20] ::(Num t,Enum t)=&gt; [T]
也是多态的,允许你写
前奏&GT; [1..20] :: [国际]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
前奏&GT; [1..20] :: [双]
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0]
只有当您不提供任何签名时,ghci才会默认为“最安全的赌注”,即4
。
因此,对于Integer
,您根本不需要[1..20]
。如果某些元素不是直接作为文字给出,而是固定类型fromInteger
的外部常量/参数,则需要它。
前奏&GT;设x = 13 ::整数
前奏&GT; :t [1..12] ++ [x] ++ [14..20]
[1..12] ++ [x] ++ [14..20] :: [整数]
前奏&GT; map fromInteger([1..12] ++ [x] ++ [14..20]):: [Int]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
这适用于您请求的任何数字结果类型,因为尽管Integer
阻止了x
多态,但[1..12]++[x]++[14..20]
重新引入了这种结果。
前奏&GT; :t map fromInteger([1..12] ++ [x] ++ [14..20]):: [Int]
map fromInteger([1..12] ++ [x] ++ [14..20]):: Num b =&gt;并[b]
<小时/> 1 实际上并不意味着
fromInteger
形成Double
或甚至Integer
的子类型......它没有;但这只会成为大数字的问题。