I’m writing a function that reduce free words. One can consider it as the following algorithm:
The idea is to cancel items in the list, if they are negative of each other and adjacent to each other. Apply it repeatedly until there is no more to cancel. For example
[-2,1,-1,2,3] -> [-2,2,3]->[3]
I wrote the following code. It doesn’t seem elegant. It uses head, tail many times, and there are total of 3 patterns for this function’s input, it be nice if it can be reduced to 2.
I want to know if there are more elegant ways to write it in Haskell. I suspect I can use fold for this, but I don’t see how to do it naturally.
freeReduce [] = []
freeReduce [x] = [x]
freeReduce (x:xs)
| x == -(head xs) = freeReduce (tail xs)
| otherwise = if' (rest == [])
[x]
(if' (x == - (head rest)) (tail rest) (x:rest))
where rest = freeReduce xs
This is the clearest I can make it:
Or equivalently:
(Both untested.)
It seems that
freeReduceis inherently strict.(My original, incorrect attempt:
(Untested.))