How do I modify this Haskell function so I don't have to import Data.Bool and only use prelude function?

197 views Asked by At

I want to build function below using only prelude built in function without importing Data.Bool. I want to replace bool function to something else so I don't have to import Data.Bool and function prints same output as below function. How can I do this so it returns same output?

increment :: [Bool] -> [Bool]
increment x = case x of
  [] -> [True]
  (y : ys) -> not y : bool id increment y ys
2

There are 2 answers

0
K. A. Buhr On

@dfeuer suggested in a comment that you should throw away this code because it's disgusting, and instead try to write it yourself. This might be distressing to you if you're the one that wrote the code in the first place and can't see why it's disgusting, so allow me to elaborate.

In fact, "disgusting" is too strong a word. However, the code is unnecessarily complex and difficult to understand. A more straightforward implementation does all the processing using pattern matching on the function argument:

increment :: [Bool] -> [Bool]
increment [] = [True]
increment (False : rest) = True  : rest
increment (True  : rest) = False : increment rest

This code is easier to read for most people, because all of the decision logic is at the same "level" and implemented the same way -- by inspecting the three patterns on the left-hand side of the definitions, you can see exactly how the three, mutually exclusive cases are handled at a glance.

In contrast, the original code requires the reader to consider the pattern match against an empty versus not empty list, the effect of the "not" computation on the first boolean, the bool call based on that same boolean, and the application of either the function id or the recursive increment on the rest of the boolean list. For any given input, you need to consider all four conceptually distinct processing steps to understand what the function is doing, and at the end, you'll probably still be uncertain about which steps were triggered by which aspects of the input.

Now, ideally, GHC with -O2 would compile both of these version to exactly the same code internally. It almost does. But, it turns out that due to an apparent optimization bug, the original code ends up being slightly less efficient than this rewritten version because it unnecessarily checks y == True twice.

0
Renegatto On

bool from Data.Bool is doing exactly the same thing as a if statement, so it can be a way to implement it:

    bool x y b = if b then y else x