Chadderz
Chadderz

Reputation: 97

Second Filtering Condition not working as intended - Haskell

I have a problem whereby I have a list of tuples ("Song Name", "Artist Name", SalesFig) and I have to filter out a tuple within that list that contain a specific Song Name and Artist Name and return all the other tuples within that list.

Below is my code:

testData = [("No Lie", "Sean Paul feat. Dua Lipa",  100),
        ("Yes Lie", "Sean Paul feat. Dua Lipa",  10),
        ("Fear & Delight", "The Correspondents",  120),
        ("Hello", "Adelle", 4)]

filterTrack :: String -> String -> [(String, String, Int)] -> [(String, String, Int)]
filterTrack songName artistName items = filter p items
    where p (song', artist', _) = songName /= song' && artistName /= artist'

Now the problem I am having with the codee is that when I want to filter one of the two songs within the list and enter say filterTrack "Yes Lie" "Sean Paul feat. Dua Lipa" testData to remove "Yes Lie" from, the list, the program removes the other song by the same artist, "No Lie", as well.

I am unsure why this is happening as I have an expression which requires the entry to not match with songName and artistName. I could understand why this is happening if there was an OR rather than an AND as it would be true if either one of the conditions were true.

I would have thought using an AND would make is so it returns every tuple that exactly doesn't match with the Song Name and the Artist Name, not just Artist Name

Upvotes: 1

Views: 62

Answers (2)

Chadderz
Chadderz

Reputation: 97

Based on hints from @arrowd, changing where p (song', artist', _) = songName /= song' && artistName /= artist' to where p (song', artist', _) = songName /= song' || artistName /= artist' solved my issue.

Upvotes: 0

Alain O'Dea
Alain O'Dea

Reputation: 21686

This is your filter function:

p (song', artist', _) = songName /= song' && artistName /= artist'

It is equivalent to this pseudo-code:

NOT sameArtist AND NOT sameSong

Which is, by De Morgans Theorem, equivalent to:

NOT (sameArtist OR sameSong)

Which is not what you want, but explains the behaviour you are seeing.

What you want your filter to be is:

NOT (sameArtist AND sameSong)

Which is written as:

p (song', artist', _) = not (songName == song' && artistName == artist')

Upvotes: 2

Related Questions