在同一函数的不同模式之间共享变量的惯用方法是什么?

thi*_*ndy 5 haskell

我开始熟练地使用 Haskell 编写代码,并且我注意到我已经犯过几次的错误模式:

doFoo :: ...
doFoo pattern1 = fooHelper ...
doFoo pattern2 = fooHelper ...
  where
    fooHelper = ...
Run Code Online (Sandbox Code Playgroud)

fooHelper当然不在范围之内doFoo pattern1。我发现自己通过使用单个无可辩驳的模式来纠正错误doFoo,然后使用函数内的 case 表达式对其进行模式匹配:

doFoo :: ...
doFoo irrefutable = case irrefutable of
  pattern1 -> fooHelper ...
  pattern2 -> fooHelper ...
  where
    fooHelper = ...
Run Code Online (Sandbox Code Playgroud)

fooHelper现在当然在这两种模式的范围内。

据我所知,函数级别的模式匹配在各个方面都等同于 case 表达式中的模式匹配(如果我错了,请纠正我),所以这似乎是一个合理的做法。这种模式是否被认为是惯用的,或者是否有更好的(或只是常用的替代方案)方法?

sna*_*nak 5

我认为在这种情况下将其转换为 case 表达式是很常见的。除此之外,通过LambdaCase扩展,你可以让它变得更短一些。

doFoo :: ...
doFoo = \case
  pattern1 -> fooHelper ...
  pattern2 -> fooHelper ...
  where
    fooHelper = ...
Run Code Online (Sandbox Code Playgroud)

从 GHC 9.4.1 开始,您甚至可以对多个参数进行模式匹配。因此,例如,您可以编写如下内容:

doFoo :: ...
doFoo = \cases
  pattern1 pattern1' -> fooHelper ...
  pattern2 pattern2' -> fooHelper ...
  where
    fooHelper = ...
Run Code Online (Sandbox Code Playgroud)

而不是写作

doFoo :: ...
doFoo x y = case (x, y) of
  (pattern1, pattern1') -> fooHelper ...
  (pattern2, pattern2') -> fooHelper ...
  where
    fooHelper = ...
Run Code Online (Sandbox Code Playgroud)

请注意,它是\cases, 不是\case