2016-06-24 3 views
1

У меня есть список списков кортежей:фильтр кортежей в списке списков [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. 

Как я могу решить эту проблему? Спасибо!

+1

'compute' ничего не делает с' m' и '(x, y)'? – josejuan

ответ

3

Давайте сделать несколько шагов, чтобы упростить функцию compute и выяснить проблему:

  1. Прежде всего, [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) 
    
  2. Функция вы передаете к filter излишне сложным, мы можем заменить его \(a,_) -> a /= 1 или даже (/=1) . fst, чтобы сделать его менее шумным. Делать это дает нам:

    compute m (x,y) = filter ((/=1) . fst) list 
    
  3. Я бы сказал, что теперь гораздо легче увидеть проблему. Ваш list имеет тип [[(Int, (Int, Int))]], т.е. это список списков кортежей.

    Но предикат, который вы передаете в filter, ожидает кортеж, поэтому filter сам ожидает список кортежей.

    Это очевидное несоответствие типа. Как мы это решаем? Я не знаю, это зависит от вас, но я думаю, вы хотите отфильтровать внутренний список.

    Как мы это сделаем? Ну, нам нужно пройти через каждый из внутренних списков, отфильтровать их и поместить отфильтрованные в новый список. Это именно то, что может помочь нам с map (или fmap). Давайте карту фильтр мы сконструированный над list:

    compute m (x,y) = map (filter ((/=1) . fst)) list 
    
  4. К сожалению, до сих пор выше дает нам ошибку типа:

    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 s, но мы фильтруем что-то немного другое.

На данный момент я не знаю, что вы хотели бы сделать, так что я просто закончить здесь, но я подозреваю, что вам необходимо либо изменить compute «s тип подписи или вам нужно каким-то образом merge m с отфильтрованными результатами для создания новой матрицы.

+0

Следуя вашим мудрым объяснениям, я закончил писать compute 'm (x, y) = map (filter ((/ = 1). Fst)) (checkAround m (x, y))' using 'checkAround m (x, y) '(как вы заметили), который возвращает тип CMatrix = [[(Int, (Int, Int))]]. Очень понятно и понятно, спасибо @ f4st! – Romeo

+0

@ Ромео Нет проблем, надеюсь, что это сработает для вас. – f4st

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 не какое-то странно структурированное разреженная матрица представления, я думаю, что конечный результат, что вы описали.

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) ]