【问题标题】:Pattern matching and arity in Haskell [duplicate]Haskell中的模式匹配和arity [重复]
【发布时间】:2021-08-13 20:46:29
【问题描述】:

在尝试定义与重复评估相对应的 Haskell 函数时,我遇到了“方程给出不同的数量”错误。这是我的代码:

nEvals :: Int -> (a -> a) -> a -> a
nEvals 1   = ($) --equivalent to nEvals 1 f x = f x
nEvals k f = (nEvals (k - 1) f) . f --equivalent to nEvals k f x = nEvals (k - 1) f (f x)

我不太明白为什么 Haskell 会给出这个错误,因为我使用的是模式匹配,而不是为给定的一组输入明确分配一个值。也许 Haskell 只允许对固定数量的参数进行模式匹配?如果是这样,有人可以解释为什么做出这个决定吗?

【问题讨论】:

  • 您可以跳过模式匹配并将其视为折叠:使用replicate 列出k 函数,然后使用foldr (.) id 将它们组合成一个函数。
  • 我相信这个问题是重复的,因此我关闭了它。如果您不同意,并且认为您的问题更细微,请随时解释原因,以便我们可以投票重新开放。
  • @chepner,哦,好主意!没想到,谢谢!
  • @chi,对不起,这和我想问的一样,我一定错过了这个问题。
  • @PrimeNumbers 完全没问题 :) 。我的不是抱怨——我只是想确保我没有太仓促地关闭它。

标签: haskell


【解决方案1】:

您应该在函数定义的所有子句中指定相同数量的参数。因此,这意味着您将其实现为:

nEvals :: Int -> (a -> a) -> a -> a
nEvals 1 f = f  -- added f as parameter
nEvals k f = (nEvals (k - 1) f) . f

我们还可以通过以下方式减少参数数量:

nEvals :: Int -> (a -> a) -> a -> a
nEvals 1 = id
nEvals k = (.) =<< nEvals (k - 1)

【讨论】:

  • 我避免了第一个实现,因为我想尽量减少数字参数,因为这对我来说更美观。刚学Haskell,所以对第二个实现中的“=
【解决方案2】:

Haskell 报告section 4.4.3.1 需要它:

函数绑定将变量绑定到函数值。变量 x 的函数绑定的一般形式是:

x p11 … p1k  match1
…
x pn1 … pnk  matchn

其中每个 pij 都是一个模式,[...]

请注意,定义函数的所有子句必须是连续的,并且每个子句中的模式数量必须相同

它没有明确说明原因,但确实说明了:

翻译:函数的一般绑定形式在语义上等价于等式(即简单模式绑定):

x = \ x1 … xk -> case (x1, …, xk) of
 (p11, …, p1k) match1
 …
 (pn1, …, pnk) matchn

对于不同数量的模式,这种翻译是不可能的。

也许可以用例如来定义行为

case (x11, …, x1k) of
  (p11, …, p1k) match1
  _ -> case (x21, …, x2k) of
         (p21, …, p2k) match2
         _ ->  ...

但是编译器很难高效地工作,这似乎是一团糟。

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2021-05-22
    • 1970-01-01
    相关资源
    最近更新 更多