为什么在 Haskell 中使用范围时映射 return 是一个附加元素?
Why does map return an additional element when using ranges in Haskell?
刚开始学习Haskell发现了一件奇怪的事
让我们列一个清单:
ghci> [0,2..5]
[0,2,4]
它有3个元素。当我对这个列表使用 map
时,我得到 3 个元素作为输出,例如:
ghci> map (+ 1) [0,2..5]
[1,3,5]
ghci> map (* 2) [0,2..5]
[0,4,8]
ghci> map (`div` 2) [0,2..5]
[0,1,2]
但是当我使用小数除法时,我在输出列表中得到了 4 个元素:
ghci> map (/ 2) [0,2..5]
[0.0,1.0,2.0,3.0]
ghci> length (map (/ 2) [0,2..5])
4
你能解释一下为什么 map
可能 return 比原来更多的元素吗?
谢谢!
这是由于 Enum
对 Float
和 Double
的实施:
> [0,2..5] :: [Float]
[0.0,2.0,4.0,6.0]
不是map
做的,而是Float
做的。具体来说,如果您调用 enumFromThenTo 0 2 5 :: [Float]
,您将获得相同的列表。您会看到 Double
.
的相同结果
这在 the haskell report 中有所暗示,但行为绝对不明显。本质上,它归结为 numericEnumFromThenTo
的实现(我们在这里进入一些 Haskell 内部),它被 Enum Float
实例使用:
numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
where
p | n' >= n = (<= m + (n' - n) / 2)
| otherwise = (>= m + (n' - n) / 2)
numericEnumFromThen n m = iterate (+ (m - n)) n
因此您 numericEnumFromThen 0.0 2.0
生成了列表 [0.0,2.0,4.0,6.0,8.0,...]
,然后您对其执行 takeWhile p
,在这种情况下相当于函数 \x -> x <= 5.0 + (2.0 - 0.0) / 2
,或更多只是 \x -> x <= 6.0
,这就是 6.0
包含在 [0.0,2.0..5.0]
.
的输出列表中的原因
我无法解释为什么它是这样实现的,这对我来说也很莫名其妙,但希望我已经回答了如何 的实施。
刚开始学习Haskell发现了一件奇怪的事
让我们列一个清单:
ghci> [0,2..5]
[0,2,4]
它有3个元素。当我对这个列表使用 map
时,我得到 3 个元素作为输出,例如:
ghci> map (+ 1) [0,2..5]
[1,3,5]
ghci> map (* 2) [0,2..5]
[0,4,8]
ghci> map (`div` 2) [0,2..5]
[0,1,2]
但是当我使用小数除法时,我在输出列表中得到了 4 个元素:
ghci> map (/ 2) [0,2..5]
[0.0,1.0,2.0,3.0]
ghci> length (map (/ 2) [0,2..5])
4
你能解释一下为什么 map
可能 return 比原来更多的元素吗?
谢谢!
这是由于 Enum
对 Float
和 Double
的实施:
> [0,2..5] :: [Float]
[0.0,2.0,4.0,6.0]
不是map
做的,而是Float
做的。具体来说,如果您调用 enumFromThenTo 0 2 5 :: [Float]
,您将获得相同的列表。您会看到 Double
.
这在 the haskell report 中有所暗示,但行为绝对不明显。本质上,它归结为 numericEnumFromThenTo
的实现(我们在这里进入一些 Haskell 内部),它被 Enum Float
实例使用:
numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
where
p | n' >= n = (<= m + (n' - n) / 2)
| otherwise = (>= m + (n' - n) / 2)
numericEnumFromThen n m = iterate (+ (m - n)) n
因此您 numericEnumFromThen 0.0 2.0
生成了列表 [0.0,2.0,4.0,6.0,8.0,...]
,然后您对其执行 takeWhile p
,在这种情况下相当于函数 \x -> x <= 5.0 + (2.0 - 0.0) / 2
,或更多只是 \x -> x <= 6.0
,这就是 6.0
包含在 [0.0,2.0..5.0]
.
我无法解释为什么它是这样实现的,这对我来说也很莫名其妙,但希望我已经回答了如何 的实施。