7

假设我有一个函数可以进行一些计算,有几种模式;以模式匹配的形式实现。

这些模式中的大多数都对参数进行处理(以及其他不同的东西),为此我在let表达式中使用了中间变量。但是我发现在许多模式上都使用相同的模式确实是多余的let,我想知道是否有一种方法可以let为多个模式定义 a ?

这是我重复的示例let

data MyType a = Something a | Another Int [a]

myFunc (Something x) = -- return something, this isn't the point here
myFunc (Another 0 xs) =
    let intermediary = some $ treatment xs
    in doSthg intermediary 1 
myFunc (Another 1 (x:xs)) =
    let intermediary = some $ treatment xs
    in doSthg1 intermediary 1 x
myFunc (Another 2 (x:x':xs)) =
    let intermediary = some $ treatment xs
    in doSthg2 intermediary 2 x x'

您可以看到,xs当我将其用于 时,该参数始终存在intermediary,这可以被分解。它可以通过使用辅助函数轻松实现,但我想知道如果没有辅助函数,我的要求是否可行。请尽量让初学者保持简单,我希望我的例子足够清楚。

4

1 回答 1

7

可以按如下方式解决此特定问题:

myFunc2 (Something x) = returnSomething x
myFunc2 (Another n ys) = 
    let xs = drop n ys
        x = head ys 
        x' = head (tail ys)
        intermediate = some $ treatment xs 
    in case n of
        0 -> doSomething intermediate n
        1 -> doSomething1 intermediate n x
        2 -> doSomething2 intermediate n x x'

由于惰性评估xx'只有在需要它们的值时才会评估。

然而——这可是个大问题!- 当您尝试调用myFunc2 (Another 2 [])(如果doSomething2实际使用x!)时,您的代码将给出运行时错误,因为要找出是什么x,我们需要评估head ys- 这将导致空列表崩溃。您作为示例提供的代码也不起作用(另一个运行时错误),Another 2 []因为没有匹配的模式,但是提供后备案例更容易。

如果您控制输入并始终确保列表Another足够长,这可能不是问题,但重要的是要注意这个问题!

于 2013-03-14T21:13:21.537 回答