Есть ли способ переписать эту функцию, чтобы быть полной? - PullRequest
4 голосов
/ 23 мая 2019

У меня есть функция, показанная ниже, которую кто-то из Code Review предложил переписать, чтобы она была полной.Они предложили заменить звонки на getRow и (!) звонками на zip или fold.

. Я думал об этом и не могу понять, как его переписать.таким образом, и при этом у меня нет хорошего понимания того, как я научу себя переписывать это.

import Data.Matrix (Matrix, getRow, ncols)
import Data.Vector ((!))

type AdjacencyMatrix = Matrix Bool

-- Input: the graph's adjacency matrix and a vertex. 
-- Output: the list of neighbours of that vertex.
neighbours :: AdjacencyMatrix -> Int -> [Int]
neighbours mat n = filter (\m -> row ! m) [0..(ncols mat)-1]
        where row = getRow n mat

Этот фрагмент кода работает в контексте моей программы, но если n больше (ncols mat) - 1, то некоторые из вызовов row ! m завершатся неудачно.

1 Ответ

6 голосов
/ 23 мая 2019

Вы можете использовать safeGetRow :: Matrix a -> Maybe (Vector a), который вернет Nothing в случае, если индекс выходит за пределы диапазона.

Вопрос, конечно, в том, что мы делаем, если индекс выходит за пределы допустимого диапазона. Два разумных варианта:

  1. используйте Maybe [Int] вместо [Int] в качестве типа возврата и верните Nothing; или
  2. возвращает пустой список, поскольку, если узел не находится в матрице смежности, у него нет соседей.

Мы можем, например, реализовать это как:

import Data.Matrix(Matrix, safeGetRow)
import Data.Vector(toList)

neighbours :: AdjacencyMatrix -> Int -> <b>Maybe</b> [Int]
neighbours mat n = map fst . filter snd . zip [0..] . <b>toList</b> <$> safeGetRow n mat

Мы используем toList :: Vector a -> [a], чтобы предотвратить использование (!) :: Vector a -> Int -> a, которое выглядит небезопасным : вы использовали индексы коррекции, но это требует некоторой аргументации, тогда как toList является полной функцией, и, следовательно, очевидно, всегда будет давать результат.

Мы можем сделать это более компактным, используя findIndices :: (a -> Bool) -> Vector a -> Vector Int:

import Data.Matrix(Matrix, safeGetRow)
import Data.Vector(<b>findIndices</b>, toList)

neighbours :: AdjacencyMatrix -> Int -> Maybe [Int]
neighbours mat n = toList . <b>findIndices id</b> <$> safeGetRow n mat

Или мы можем использовать maybe :: b -> (a -> b) -> Maybe a -> b, чтобы использовать вместо него пустой список:

import Data.Matrix(Matrix, safeGetRow)
import Data.Maybe(<b>maybe</b>)
import Data.Vector(findIndices, toList)

neighbours :: AdjacencyMatrix -> Int -> <b>[Int]</b>
neighbours mat n = <b>maybe</b> [] (toList . findIndices id) (safeGetRow n mat)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...