在Haskell中定义函数的2个或更多个方程可以共享相同的where/let块吗?

Cha*_*ers 4 haskell functional-programming pattern-matching

在Haskell中定义函数的2个或更多个方程可以共享相同的where/let块吗?

让我提出一个人为的例子来说明这个问题.

首先,请考虑以下代码作为起点:

someFunction v1 v2 v3 = difference ^ v3
   where
      difference = v1 - v2
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是,想象一下,我需要处理一个"替代案例",如果v3 == 99并且差异<4(完全随意,但我要说那些是我的要求),我需要返回零.

我的第一个想法是这样做:

someFunction v1 v2 99 | difference < 4 = 0
someFunction v1 v2 v3 = difference ^ v3
   where
      difference = v1 - v2
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为someFunction的第一个等式和someFunction的第二个等式不是在块中共享相同的.这在这个人为的例子中并不是什么大不了的事,因为where块中只有一个变量("差异").但在现实世界中,可能存在大量变量,重复这些变量是不可接受的.

我已经知道如何通过使用警卫和只有一个方程来解决这个问题.问题是,有多种方程可以共享相同的where/let子句吗?因为似乎需要具有不同模式的多个方程而不是被迫只有一个具有许多防护的方程.

bdo*_*lan 12

一种选择是将函数提升到where块本身:

someFunction v1 v2 = f
    where
        f 99 | difference < 4 = 0
        f v3 = difference ^ v3
        difference = v1 - v2
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,where 子句(或 let 表达式)中的所有绑定在 Haskell 中都是相互递归的。在这个例子中,这意味着 `f` 可以使用 `difference`,但 `difference 也可以使用 `f`(如果它愿意的话)。因此,无论何时遇到此类问题,通常都可以通过将内容放在相同的 where 子句中来解决,就像@bdonian 所说的那样。 (2认同)