为什么在takekell中“采取”更改数据类型?

时间:2017-09-05 23:31:10

标签: haskell

我正在编写一个函数,它从列表中获取元素并返回它们。

我觉得很简单。但是当使用“take”时,例如:2 digit x job code employment 32 10 4569 32 11 4521 3 digit x job code employment 32 101 1203 32 102 3366 32 111 1000 32 112 3521 4 digit 32 1011 1203 32 1025 1000 32 1028 2366 32 1111 500 32 1112 500 32 1123 2899 32 1124 45 32 1125 577

当我真正想要take 2 [1.2,3,4]

时,它会返回[1.2,3.0]

我想创建一个遍历列表的功能并削减不必要的小数,但我无法理解它看到haskell不接受我与x&的比较

中的圆(x)
[1.2, 3]

所以答:有没有更简单的解决方案? B:为什么不能将x与圆(x)进行比较?

2 个答案:

答案 0 :(得分:11)

你说,"我其实想要[1.2, 3] [而不是[1.2, 3.0]]"。我将此解释为您需要一个包含Float s等的列表,用于小数和Int s或类似的数字,而不是小数部分。

你不能拥有这个。

Haskell中的所有列表都是同类的:每个元素都具有相同的类型。

你可以做一些事情;例如,您可以拥有标记的联合,规范示例为Either。所以

[Left 1.2, Right 3] :: [Either Double Integer]

会好的;但是你需要明确标记每个元素。

这也或多或少是为什么x == round x不起作用的答案:(==)运算符采用两个相同类型的参数;而通常round不能返回与其参数相同类型的值。您可能更喜欢properFraction

> properFraction 3
(3,0.0)
> properFraction 1.2
(1,0.19999999999999996)

您可以检查第二部分,以确定您的号码是否为整数(当时,第一部分将是round的结果)。

答案 1 :(得分:6)

take不会更改列表元素的类型。启动GHCi并继续。我的提示是>>>

>>> :t [1.2,3,4]
[1.2,3,4] :: Fractional t => [t]

这表示列表元素有一些Fractional类型。

>>> :t [1.2,3.0,4.0]
[1.2,3.0,4.0] :: Fractional t => [t]

GHCi也在这里说同样的话。发生了什么事?

>>> :t 2
2 :: Num t => t
>>> :t 2.0
2.0 :: Fractional t => t

推断出没有小数的数字文字有一些Num类型。带有小数的数字文字被推断为具有一些Fractional类型。要使两个元素位于同一列表中,它们必须具有相同的类型。 22.0的常见类型是什么?

>>> :t 2 `asTypeOf` 2.0
2 `asTypeOf` 2.0 :: Fractional a => a

所有Fractional类型都是Num类型,因此22.0的常见类型为Fractional类型。

>>> [1.2,3,4]
[1.2,3.0,4.0]

我们可以从列表的打印中看到,所有元素都被推断为Fractional类型。默认为Double

要从列表中删除不必要的小数,您必须更具体地说明您希望此列表具有哪种类型。 Int列表没有小数,Double列表总是有小数。单个列表不能同时包含IntDouble个元素。