[英]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.