假设我有一个函数可以进行一些计算,有几种模式;以模式匹配的形式实现。
这些模式中的大多数(以及其他不同的事物)对参数进行处理,我在let
表达式中使用中间变量。但是我发现在许多模式上使用相同的let
真的很多,我想知道是否有办法为几种模式定义let
?
以下是我重复的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
时,您可以看到参数{{1}}始终存在,这可能会被分解。
它可以很容易地通过使用辅助函数来实现,但我想知道如果没有一个我可能会问什么。请尽量让初学者保持简单,我希望我的例子足够清楚。
答案 0 :(得分: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'
感谢延迟评估x
,只有在需要价值的情况下才会评估x'
。
然而 - 这是一个很大的问题! - 当您尝试调用myFunc2 (Another 2 [])
时(如果doSomething2
实际使用x
!),您的代码会出现运行时错误,因为要找出x
是什么,我们需要评估head ys
- 并且会为空列表崩溃。您作为示例提供的代码也不会对Another 2 []
起作用(另一个运行时错误),因为没有匹配的模式,但是更容易提供后备案例。
如果你控制输入并且始终确保Another
中的列表足够长,这可能不是问题,但重要的是要注意这个问题!