[英]Filter tuples in list of lists [Haskell]
我有一个元组列表的列表:
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.
我该如何解决? 谢谢!
让我们采取一些步骤来简化compute
功能并找出问题所在:
首先, [row | row <- list]
[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
代替它(/=1) . fst
(/=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
与过滤后的结果合并为创建一个新矩阵。
这是您要做什么?
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
不是某种奇怪的稀疏矩阵表示形式,我也认为最终结果就是您所描述的。
问题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) ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.