为什么为负参数定义`take`和`drop`?

Lyn*_*ynn 15 haskell

前奏显示例子takedrop负参数:

take (-1) [1,2] == []
drop (-1) [1,2] == [1,2]
Run Code Online (Sandbox Code Playgroud)

为什么这些定义的方式是,例如x !! (-1)"更安全"的事情和崩溃?即使在论证没有意义的情况下,这似乎是一种使用这些函数的hackish和非Haskell类似的方法.这背后是否有一些我没有看到的更大的设计理念?这种行为是否由标准保证,或者这就是GHC决定如何实施它?

lef*_*out 13

主要有一个很好的理由take:它可以保证结果列表(如果有的话)始终具有所请求的元素数量.

现在,take已经在另一个方向违反了这一点:当你试图获取比列表中更多的元素时,只需要尽可能多的元素,即少于请求.也许不是最优雅的事情,但在实践中,这往往非常有用.

主要的不变量takedrop:

take n xs ++ drop n xs  ?  xs
Run Code Online (Sandbox Code Playgroud)

即使n是否定的,这也是正确的.

不检查列表长度的一个好理由是它使函数在惰性无限列表上运行良好:例如,

take hugeNum [1..] ++ 0 : drop hugeNum [1..]
Run Code Online (Sandbox Code Playgroud)

将立即1作为第一个结果元素.如果take并且drop首先必须检查输入中是否有足够的元素,则这是不可能的.


chi*_*chi 6

我认为这是设计选择的问题.

当前定义确保属性

take x list ++ drop x list == list
Run Code Online (Sandbox Code Playgroud)

适用于任何人x,包括负面人士以及大于length list.

然而,我可以在take/ drop哪个错误的变体中看到值:有时崩溃优先于错误的结果.

  • 那是伪代码。我的意思是,如果“drop n xs”和“take n xs”在“n ∉ [0 .. length xs-1]”时都没有产生“Nothing”,那么我们总是有“liftA2 (++) (take n xs) (drop n xs) == 只是 xs`。 (2认同)