Let's say I have a function which does some computation, with several patterns; implemented in the form of pattern matching.
Most of these patterns do (along with other things different from one to another) a treatment on a parameter, for which I use an intermediary variable in a let
expression. But I find it really redundant to have the same let
on many patterns, and I wonder if there is a way to define a let
for several patterns?
Here is an example of my duplicated 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'
You can see that the parameter xs
is always present when I use it for intermediary
, and this could be factorised.
It could easily be achieved by using a helper function but I was wondering if what I am asking is possible without one. Please try to keep it simple for a beginner, and I hope my example is clear enough.
This particular problem can be worked around as follows:
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'
Thanks to lazy evaluation x
and x'
will be only evaluated if their value is needed.
However - and this is a big however! - your code will give a runtime error when you try to call myFunc2 (Another 2 [])
(and if doSomething2
actually uses x
!) because to find out what x
is, we need to evaluate head ys
- and that'll crash for an empty list. The code you gave as an example also won't work (another runtime error) for Another 2 []
since there's no matching pattern, but there it's easier to supply a fall-back case.
This might not be a problem if you control the input and always make sure that the list in Another
is long enough, but it's important to be aware of this issue!