Filter along a list of tuples

Filter along a list of tuples

Problem Description:

I am trying to solve Day 4 of the Advent of Code and to do this I currently need to filter a list of list of tuples.

First of all, let’s get the sample

sample=[[(2,4),(6,8)],[(2,3),(4,5)],[(5,7),(7,9)],[(2,8),(3,7)],[(6,6),(4,6)],[(2,6),(4,8)]]

This sample was obtained with Data.Text.splitOn and a simple tuple-ify function ([x,y] -> (x,y)).

Then, we need to find all pairs of tuples where one contains the other. I, then, write the simple following helper

contains :: (Int,Int) -> (Int,Int) -> Bool
contains a b = (fst a) <= (fst b) && (snd a) <= (snd b)

Finally, I want to filter from the sample but I could not figure out how to do it.
Of course, I reduce the 2D list of list of tuples to a simple 1D list of tuple with map;

main :: IO ()
main = do
  print $ length $ map solution sample

where, solution is either

solution :: [(Int,Int)] -> [Bool]
solution = filter (x y -> x `contains` y || y `contains` x)

with the following error

Couldn't match type ‘(Int, Int)’ with ‘Bool’
      Expected: [(Int, Int)] -> [Bool]
        Actual: [(Int, Int)] -> [(Int, Int)]
    • In the expression:
        filter ( x y -> x `contains` y || y `contains` x)

or

solution :: [(Int,Int)] -> [(Int,Int)]
solution = filter (x y -> x `contains` y || y `contains` x)

with the following error

Couldn't match type ‘(Int, Int)’ with ‘Bool’
      Expected: [(Int, Int)] -> [Bool]
        Actual: [(Int, Int)] -> [(Int, Int)]
    • In the expression:
        filter ( x y -> x `contains` y || y `contains` x)

or

solution :: [(Int,Int)] -> [(Int,Int)]
solution = filter ([x,y] -> x `contains` y || y `contains` x)

with the following error

    • Couldn't match expected type: (Int, Int)
                  with actual type: [(Int, Int)]
    • In the pattern: [x, y]
      In the first argument of ‘filter’, namely
        ‘( [x, y] -> x `contains` y || y `contains` x)’
      In the expression:
        filter ( [x, y] -> x `contains` y || y `contains` x)

etc…

I tried everything my learning brain could think of, and this is driving me crazy since the last couple of days. What am I doing wrong?

Solution – 1

(x y -> ...) is a lambda taking two parameters. You don’t have that, you have a single tuple parameter.

([x, y] -> ...) is closer: it’s a lambda taking one parameter, a list expected to have exactly two elements. But that’s still not a two-tuple.

Instead, you want ((x, y) -> ...), a lambda taking a two-tuple parameter.

Solution – 2

I think your fundamental problem is your data representation. Your function contains takes exactly two tuples; that part’s probably good. (It’s a little unclear if your inequalities in its definition are correct, I don’t have the context to know.) But the sample you’ve extracted contains items that are each lists of tuples; there’s no guarantee of length.

I suggest re-working sample to have type [((Int, Int), (Int, Int))]. I think you’ll be able to get it working from there; if you get stuck again you could try uncurrying contains (although you’re already doing pattern matching, so you can probably ignore this).

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject