Karavana
Karavana

Reputation: 487

How to use a tuple's elements as indexes to reach a list's elements-haskell

I have a list of tuples, which I am trying to use its elements to reach a nested list's elements.

list = [["c","a","b"],["k","l","m"]]
indexTuple = [(0,1),(1,1),(1,2)]

this way I need to check whether there is an "a" in one of the elements of the list corresponding to my indexTuple's elements. My attempt so far;

seekinga :: [[[Char]]] -> Int -> Int -> Int -> [(Int,Int)]
seekinga list x y width 
        | list !!(map fst indexTuple) !!(map snd indexTuple) == "a" = [(fst indexTuple,snd indexTuple)]
        | otherwise = [()]
    where indexTuple = [(x,y) | x <- [x-width..x+width], y <- [y-width..y+width]] 

this obviously does not work, because the !! operator wants integers to work on, but map returns lists. Any suggestions are very much appreciated.

Upvotes: 2

Views: 1074

Answers (2)

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68152

You really have two separate concerns: given two numbers, how do you index into a nest list and how do you get two numbers out of a tuple.

The first problem is easy to solve just by looking at types. You know how to index into one list: (!!) :: [a] -> Int -> a. Here, a can be anything, including a nested list. So, given [[[Char]]], we can use !! to get a [[Char]]. And, since this is a list itself, we can use !! again to get a [Char]. ([Char] is just String, in case you don't realize.)

So all we need to do here is use !! then use it again on the result of the first one.

Now, how do we actually get the two numbers out? This is where we use pattern matching. We can just match against a tuple with a let statement:

let (i, j) = tuple in ...

Now just put the two together and you're set.

Upvotes: 6

Davorak
Davorak

Reputation: 7444

So you can view an element with:

> list !! 1 !! 2
"m"

So lets make this a function:

:set -XNoMonomorphismRestriction
> let index lst  i j= lst !! i !! j

And lets filter out those indexs which do not point to "a"

> filter (\(i, j) -> index list i j == "a") indexTuple
[(0,1)]

If instead list = [["c","a","b"],["k","l","a"]]

then

> filter (\(i, j) -> index list i j == "a") indexTuple
[(0,1),(1,2)]

Using !! may not be your best option however, in fact it probably is not. I tried to break out the two parts of the problem, as I understood it, access the element and filter for indexes.

Upvotes: 3

Related Questions