【问题标题】:Haskell syntax: what does drop (n+1) [] = [] mean?Haskell 语法:drop (n+1) [] = [] 是什么意思?
【发布时间】:2013-06-23 12:12:08
【问题描述】:

(n+1) 是什么意思?我知道两者都是递归 Haskell 函数,并且正在使用模式匹配。

我不明白它将如何匹配factorial (n+1) 以及factorial = 右上方的(n+1)

对于drop 函数,为什么它是drop 0 xs = xs?那么drop (n+1) [] = []呢?

--Example 1
factorial 0 = 1
factorial (n+1) = (n+1) * factorial n

--Example 2
drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop (n+1) [] = []
drop (n+1) (_:xs) = drop n xs

顺便说一句,我在编译时遇到错误。

  • 代码编译失败
  • 模式中的解析错误:n + 1

更新: 感谢您指出正确的术语。我找到了这个n+k patterns。 由于自 2010 年以来已删除 n+k 模式,我还在 how to enable this pattern 上发现了这个问题。

【问题讨论】:

  • 现在我应该接受哪个答案?两者都很棒!
  • 哪个对你帮助最大,或者如果你不能决定就不要接受。 sepp2k 和我都不会为 15 分哭泣。
  • 两者... X_X 50% 与 50%。该死!
  • @DanielFischer,如果有正确的答案,我想接受一个是很好的stackoverflow礼仪。

标签: haskell syntax functional-programming


【解决方案1】:

这些是 NPlusKPatterns,已于 2010 年从语言中删除,现在仅适用于上述语言扩展。

n + k-模式

drop (n+1) [] = []

n 绑定到参数值减一,前提是参数值为>= 1。模式与参数 <= 0 不匹配。

如果

drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop (n+1) [] = []
drop (n+1) (_:xs) = drop n xs

使用否定的Int 参数调用,例如

drop (-2) "foo"

没有模式匹配,你会得到一个异常。

一般来说,如果你定义(举个愚蠢的例子)

foo :: Int -> Int
foo (n+5) = 3*n
foo (n+2) = n
foo (n+1) = 2*n

如果你调用foo 7,第一个模式匹配和n将绑定到2,所以foo 7 = 6。如果您调用foo 3,第一个模式不匹配(3-5 = -2 < 0),但第二个匹配,并且将n 绑定到3-2 = 1,因此foo 3 = 1。如果你调用foo 1,前两个模式都不匹配,但最后一个匹配,然后n 绑定到1 - 1 = 0,所以foo 1 = 0。使用参数 < 1 调用 foo 会引发异常。

为什么是drop 0 xs = xs?那么drop (n+1) [] = []呢?

好吧,drop 0 从列表的前面删除了 0 个元素,因此它根本不会更改列表参数。而且你不能从空列表中删除元素,所以drop (n+1) [] = [] 是除了引发错误之外你唯一能做的事情。

【讨论】:

  • 困惑,所以你说我作为新手 Haskeller 不需要学习这种模式?
  • 或多或少。如果您从中学习的书/教程(广泛)使用它们,您需要(并且将)学习它们。但它们已从语言中删除是有原因的,您不会在生产代码中看到很多 n+k-patterns。
  • 困惑 = 这也是他们删除它的部分原因。
【解决方案2】:

这是一个所谓的n+k 模式。模式(n+1) 匹配任何正整数,并为n 提供该整数减一的值。因此,如果您调用drop 1 xsn 的值将为 0。

为什么是drop 0 xs = xs

因为如果从列表中删除 0 个元素,最终会得到相同的列表。

那么drop (n+1) [] = []呢?

也就是说,如果您从空列表中删除任意数量的项目,您最终会得到一个仍然为空的列表。除了失败并显示错误消息之外,在这种情况下,这确实是您可以做的唯一明智的事情。

【讨论】:

  • “它匹配任何正整数,并给 n 那个整数的值减一。”现在我完全糊涂了……!!!
  • @Jeff 如果你调用drop 1 xs,那么n 为0,因为0+11,所以drop 1 xs 匹配drop (0+1) xs,后者匹配n=0drop (n+1) xs
  • @Jeff 对不起,是的,我在那句话中特别提到了n+1。通常n+k 模式匹配大于或等于k 的数字,并给出n 该整数减去k 的值。
  • @Jeff 不,从来没有n-k 模式。呃,我只是想象有,sombody 混合了 n+kn-k 模式。
  • k 是严格正数吗? (可以使用n+(-1)吗?)
【解决方案3】:

您提供的代码使用了名为NPlusKPatterns 的功能,它不再是标准haskell 的一部分(不在haskell2010 标准中),但可以通过将行“导入”它 {-# LANGUAGE NPlusKPatterns #-} 在源文件的顶部。

让我们看一个如何使用它的例子:

myFunction 0 = 0
myFunction (n+1) = n

这个函数有点傻。如果输入为0,则结果为0。对于正输入数m,结果是m - 1,或者换一种说法,对于正输入数n+1,结果是n。由于(n+1) 模式与负数不匹配,因此该函数未定义负数。

现在假设我将函数更改为

myFunction 0 = 0
myFunction (n+1) = (n+1)

现在左边有一些魔法。它声明了一个变量n,它是输入减一。另一方面,右侧使用(+) 运算符添加一个。

至于您对drop 函数的问题。 drop 0 xs = xs 表示从列表中删除 0 元素不会更改列表。 drop (n+1) [] = [] 只是从空列表中删除任何正数的元素都是空列表。

haskell2010报告中drop的定义是:

drop n xs     | n <= 0 =  xs
drop _ []              =  []
drop n (_:xs)          =  drop (n-1) xs

它的行为有些不同,因为它是为负数定义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多