DkM
DkM

Reputation: 800

Result depends on order of list even though it should not

I am spending a little time on Haskell in my holidays, but now I've run into a problem. I have a list which consists of booleans, and I am trying to make a function which takes a list of integers and flips the booleans at the corresponding positions.

If you load the following piece of code into GHCi and try to run flipBits testBoard [1,0,2] the result is [True, True, False, False]. If you run it with flipBits testBoard [1,2,0] the result is [True, True, True, False].

I would like the result not to be dependent on the order of the numbers in the list passed to flipBits (apparently a 0 in the list stops the execution). What am I doing wrong?

flipBit board which (x:xs)
    | which == 0 = (not (board !! which)):xs
    | otherwise =  x:(flipBit board (which-1) xs)

flipBits board [] = board
flipBits board (x:xs) = flipBits (flipBit board x board) xs

testBoard = take 4 $ repeat False

Upvotes: 0

Views: 84

Answers (2)

Daniel Fischer
Daniel Fischer

Reputation: 183968

In your flipBit function

flipBit board which (x:xs)
    | which == 0 = (not (board !! which)):xs
    | otherwise =  x:(flipBit board (which-1) xs)

You replace all elements of the board that you want to flip with not (board !! 0), since the only flipping is when which reaches 0.

You simply want to remove one argument from that,

flipBit which (x:xs)
    | which == 0 = not x : xs
    | otherwise  = x : flipBit (which - 1) xs

and then have

flipBits board (x:xs) = flipBits (flipBit x board) xs

or, since that is a recurring pattern of application, use the appropriate higher order function,

flipBits board ixs = foldr flipBit board ixs

Upvotes: 2

dave4420
dave4420

Reputation: 47062

    | which == 0 = (not (board !! which)):xs

The guard says that the RHS is only going to be evaluated when which is 0, so this is the same as

    | which == 0 = (not (board !! 0)):xs

board here is the "original" board, before we started walking along it. So instead of flipping the bit at a certain position, the bit is replaced by the inverse of the bit at the head of the list.

You should instead do

    | which == 0 = not x : xs

and then ask yourself why you need the first parameter to flipBit.

Upvotes: 1

Related Questions