将Integer类型的列表转换为Int类型的列表

时间:2014-06-07 07:44:27

标签: haskell

我正在尝试将此列表[1..20]从[Integer]转换为[Int]

map fromInteger [1..20]

但是这仍然给我一个整数列表

这就是它自己的转换2,它是Integer类型到Int     fromInteger 2 :: Int

出了什么问题

1 个答案:

答案 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的子类型......它没有;但这只会成为大数字的问题。