我有一个元组列表列表:
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))]]
我想按每个元组的第一个值过滤它们。 这就是我试过的......
compute :: Matrix -> Coordinates -> Matrix
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- list]
带
type Matrix = [[Int]]
type Coordinates = (Int, Int)
这是我得到的错误:
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.
我该如何解决这个问题? 谢谢!
答案 0 :(得分:4)
让我们采取一些步骤来简化compute
函数并找出问题所在:
首先,[row | row <- list]
不执行任何操作,它只相当于list
,因此我们可以删除它并将其替换为list
,以使该功能更易于阅读:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) list
顺便说一下,在你的消息中,我看到list
不是实际调用过滤器的参数。相反,它是checkAround m (x, y)
,因此compute
应该看起来像这样:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) $ checkAround m (x, y)
您传递给filter
的功能不必要地复杂,我们可以将其替换为\(a,_) -> a /= 1
甚至(/=1) . fst
,以减少噪音。这样做可以让我们:
compute m (x,y) = filter ((/=1) . fst) list
我说现在看到这个问题要容易得多。您的list
类型为[[(Int, (Int, Int))]]
,即。它是元组列表的列表。
但是你传入filter
的谓词期待一个元组,因此filter
本身就是期待一个元组列表。
这是明显的类型不匹配。我们如何解决这个问题?我不知道,这取决于你,但我想你想要过滤内部列表。
我们怎么做?好吧,我们需要遍历每个内部列表,过滤它们并将过滤后的列表放入新列表中。这正是map
(或fmap
)可以帮助我们的内容。让我们映射我们在list
上构建的过滤器:
compute m (x,y) = map (filter ((/=1) . fst)) list
不幸的是,上面仍然给出了类型错误:
Couldn't match type ‘(Integer, (Integer, Integer))’ with ‘Int’
Expected type: [[Int]]
Actual type: [[(Integer, (Integer, Integer))]]
那么,为什么呢?我们知道Actual type
是list
的类型以及已过滤列表的类型,但Expected type
是什么,为什么它是[[Int]]
?
答案取决于您的类型签名Matrix -> Coordinates -> Matrix
。 compute
应该会生成Int
个列表的列表,但我们会过滤一些不同的内容。
此时我真的不知道你想做什么,所以我会在这里结束,但我怀疑你需要改变compute
的类型签名,或者你需要以某种方式将m
与过滤后的结果合并以创建新矩阵。
答案 1 :(得分:0)
这是你想要做的吗?
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]
即使你的list
不是某种奇怪结构的稀疏矩阵表示,我认为最终的结果就是你所描述的。
答案 2 :(得分:0)
问题1:您对compute
的定义是list
,但list
不是参数。
问题2:如果您将list
更改为m
,那么您的代码是正确的,但您提供的类型签名不正确。
解决方案:
将list
更改为m
,并且不为类型提供签名:
compute m (x,y) = filter (\(a,(_,_)) -> a /= 1) [row | row <- m]
现在问ghci
类型签名应该是什么:
ghci> :t compute
compute
:: (Eq a, Num a) => [(a, (t2, t3))] -> (t, t1) -> [(a, (t2, t3))]
现在你看到type Matrix
应该定义为
type Matrix = [ (Int, (Int,Int) ]