I have a list of lists of tuples:
let list = [[(1,(2,2)),(0,(3,2)),(0,(4,2))],[(0,(2,3)),(0,(3,3)),(0,(4,3))],[(0,(2,4)),(0,(3,4)),(0,(4,4))]]
I would like to filter them by the first value of each tuple. That's what I tried...
compute :: Matrix -> Coordinates -> Matrix
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- list]
with
type Matrix = [[Int]]
type Coordinates = (Int, Int)
That's the error I got:
ContiguousRegion.hs:20:36:
Couldn't match expected type ‘[Int]’
with actual type ‘(Integer, (t0, t1))’
In the pattern: (a, (_, _))
In the first argument of ‘filter’, namely
‘(\ (a, (_, _)) -> a /= 1)’
In the expression:
filter
(\ (a, (_, _)) -> a /= 1) [row | row <- checkAround m (x, y)]
ContiguousRegion.hs:20:58:
Couldn't match type ‘(Int, (Int, Int))’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, (Int, Int))]
In the expression: row
In the second argument of ‘filter’, namely
‘[row | row <- checkAround m (x, y)]’
Failed, modules loaded: none.
How can I solve this? Thanks!
Let's take a few steps to simplify the compute
function and figure out the problem:
First of all, [row | row <- list]
[row | row <- list]
does nothing, it's equivalent to just list
, so we can remove it and replace it with list
, to make the function easier to read:
compute m (x,y) = filter (\\(a,(_,_)) -> a /= 1) list
By the way, in your message I see that list
isn't what the argument to filter is actually called. Instead, it's a checkAround m (x, y)
, so compute
should probably look like this:
compute m (x,y) = filter (\\(a,(_,_)) -> a /= 1) $ checkAround m (x, y)
The function you're passing to filter
is unnecessarily complicated, we can replace it with \\(a,_) -> a /= 1
or even (/=1) . fst
(/=1) . fst
to make it less noisy. Doing that gives us:
compute m (x,y) = filter ((/=1) . fst) list
I'd say it's now much easier to see the problem. Your list
has the type [[(Int, (Int, Int))]]
, ie. it's a list of lists of tuples.
But the predicate your passing into filter
is expecting a tuple, therefore filter
itself is expecting a list of tuples.
This is an obvious type mismatch. How do we solve this? I don't know, that's up to you, but I guess you want to filter the inner list.
How do we do this? Well, we need to go through each of the inner lists, filter them and put the filtered ones in a new list. This is exactly what map
(or fmap
) can help us with. Let's map the filter we've constructed over list
:
compute m (x,y) = map (filter ((/=1) . fst)) list
Unfortunately, the above still gives us a type error:
Couldn't match type '(Integer, (Integer, Integer))' with 'Int' Expected type: [[Int]] Actual type: [[(Integer, (Integer, Integer))]]
Well, why is that? We know that the Actual type
is the type of list
and the type of the filtered list as well, but what is the Expected type
and why is it a [[Int]]
?
The answer lies in your type signature, Matrix -> Coordinates -> Matrix
. compute
is supposed to produce a list of lists of Int
s, but we're filtering something a bit different.
At this point I don't really know what you'd like to do, so I'll just end here, but I suspect you either need to change compute
's type signature or you need to somehow merge m
with the filtered results to create a new matrix.
Is this what you are trying to do?
type SparseMatrix = [Row]
type Row = [Element]
type Element = (Int, Coordinates)
type Coordinates = (Int, Int)
removeRowVal :: Row -> Int -> Row
removeRowVal row i = filter ((/= i).fst) row
removeSMVal :: SparseMatrix -> Int -> SparseMatrix
removeSMVal sm i = [removeRowVal row i | row <- sm]
Even if your list
is not some kind of oddly structured sparse matrix representation, I think the final result is what you described.
Problem 1: Your definition of compute
refers to list
, but list
is not a parameter.
Problem 2: If you change list
to m
your code is correct, but the type signature you gave is not correct.
Solution:
Change list
to m
, and don't give a type a signature:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- m]
Now ask ghci
what the type signature should be:
ghci> :t compute
compute
:: (Eq a, Num a) => [(a, (t2, t3))] -> (t, t1) -> [(a, (t2, t3))]
Now you see that that type Matrix
should be defined as
type Matrix = [ (Int, (Int,Int) ]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.