【问题标题】:Why Does Haskell's Range Syntax use First and Then rather than First and Step?为什么 Haskell 的范围语法使用 First and Then 而不是 First and Step?
【发布时间】:2017-03-15 05:34:50
【问题描述】:

我刚开始学习 Haskell,对范围的行为感到惊讶。

我知道[1, 2 .. 10]enumFromThenTo 1 2 10 的语法糖。

从其他编程语言(例如 Python)我习惯于使用 firstlaststep 参数指定范围,使得 Haskell 的 then 等价于 Python 中的 first+step

为什么 Haskell 使用 then 而不是 step 来定义序列中值之间的间距?

【问题讨论】:

标签: haskell range


【解决方案1】:

请注意,例如Python 的范围说明符是一个函数

>>> range(1, 12, 2)
[1, 3, 5, 7, 9, 11]

Haskell 旨在提供的语法看起来就像您可以为另一个人写出列表,写成 .. 而不是“显而易见的”模式:

ghci> [1, 3 .. 11]
[1,3,5,7,9,11]

另一点(Carl 在对 leftaroundabout 的回答的评论中提出)是序列语法可用于非数字类型,其中没有这么简单的方法来编写“步骤”:

ghci> ['a', 'f' .. 'z']
"afkpuz"

【讨论】:

  • 同意,即使我认为Enum 类型应该与Int 的段同构,因为我们有toEnum / fromEnum,所以应该很好地定义Int 步进。将浮点类型设为Enums 对我来说是个错误。 (或者,或者,这两个函数应该移动到另一个类)
  • @chi 是的,有时候我希望一个类型是可枚举的,但对 Int 没有很好的同构。我宁愿toEnum / fronEnum 在不同的班级;在 Enum 中进行多态时,您不能真正明智地使用它们,您必须更多地了解所使用的特定类型。但大多数情况下,我发现我只在知道自己在使用什么时才使用 Enum 的东西,所以这并不是很重要。
【解决方案2】:

以 Ben 和 Carl 所说的话为基础:

Enum 中定义的函数是多态的,例如

λ> :t enumFromThenTo
enumFromThenTo :: Enum a => a -> a -> a -> [a]

通过将它们定义为“第一、第二、最后”,我们可以对所有参数使用相同的多态类型参数a

如果我们将它们定义为“first, last, step”,那么step 参数的类型可能与其他两个不同。

  • 对于整数序列,步长也是整数 - 没问题。
  • 对于字符序列,步长又是一个整数——所以也许我们可以将step 的类型固定为某种整数类型? (但是是哪一个?)
  • 但是不行 - 对于浮点序列,步骤也需要是浮点数!

所以我们需要(我认为!)向 Enum 类型类添加另一个类型变量,这会使它变得更加复杂,并且(可能 - 尚未检查)需要 GHC 扩展而不是标准 Haskell。

【讨论】:

  • 另一种选择是说['A'..'Z', succ . succ . succ] for ` ['A', 'D' .. 'Z']` 但它当然更难阅读,更容易用@写987654326@
  • Enum 真的很奇怪,因为toEnum . (+ k) . fromEnum 的类型很好,因此Int 步进似乎总是合理的。浮点类型,IMO 不应该被做成Enum(否则toEnum,fromEnum 应该属于另一个类)
  • @chi toEnum . (+k) . fromEnum 可能是好类型的;但这并不意味着它表达了你想要的所有行为。出于这个原因,我认为Float/Double 的答案示例是一个很好的示例:当前支持的某些步骤不适合您提出的模式。
【解决方案3】:

我同意,IMO start-step-end 会是更好的约定。然而,start-then-end 更常见于纯数学环境中,这是 Haskell 的传统。

请注意,您可以很容易地手动实现

  • 开始-步骤-结束:

    takeWhile (<end+step/2) $ iterate (+step) start
    
  • 开始步数:

    take count $ iterate (+step) start
    

而 start-then-end 需要先手动计算步骤

let step = then - start
in takeWhile (< end+step/2) $ iterate (+step) start

因此,为难以手动实现的表达式添加语法糖/标准函数是有意义的。

【讨论】:

  • 另一个真正的关键点是它不限于数字类型。
猜你喜欢
  • 2018-01-26
  • 2011-02-16
  • 2015-09-03
  • 2018-04-06
  • 1970-01-01
  • 2018-09-15
  • 2021-06-28
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多