haskell - 为什么在 Haskell 中使用范围时 map 会返回一个附加元素?

标签 haskell range division

我刚开始学习 Haskell,发现了一件奇怪的事情。

让我们有一个 list :

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可能会返回更多元素吗?

谢谢!

最佳答案

这是由于 Enum 的实现对于 FloatDouble :

> [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 - 为什么在 Haskell 中使用范围时 map 会返回一个附加元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32364887/

相关文章:

function - 非边褶皱的特性是什么?

haskell - 是什么让 Bytestring "lazy"?

python - 获取 x 和 y 之间的 n 个数字的列表

algorithm - 用固定常数执行整数硬件除法的最快方法是什么?

load - promQL如何将node_load除以核心数

c++ - 自定义 "Very Long Int"分区问题

haskell - Clojure 中的 Identity 函数与 Haskell 中的 id 函数具有相同的用法和用途吗?

class - Haskell 类属性检查

string - 从常量 Ints 创建 Range<String.Index>

python - 如何搜索单个整数的范围?