Haskell: удаление элемента из списка списков кортежей с помощью кортежа - PullRequest
0 голосов
/ 12 марта 2020

У меня есть структура в моем коде, которая включает в себя один список, который имеет много списков, а затем эти списки имеют кортежи, которые представляют координаты. Вот моя ситуация:

type Point = (Int, Int)
type ShipPoints = [Point]

removeCoordinatePairFromList :: Point -> [ShipPoints] -> [ShipPoints]
removeCoordinatePairFromList fireCoordinate enemyShips =  (filter (notElem fireCoordinate) enemyShips)

Однако это работает не так, как я хочу. Это удаляет весь подсписок внутри родительского списка, где найдена совпадающая пара координат. Я хочу, чтобы только один кортеж, который соответствует fireCoordinate, был удален из подсписка, а все остальное осталось прежним. Контекст - это игра линкора, а тип ShipPoints представляет любой тип координат корабля в списке. [ShipPoints] означает все координаты корабля от одного игрока.

1 Ответ

1 голос
/ 13 марта 2020

Похоже, вы хотите go просмотреть список ShipPoints и удалить Point из каждого ShipPoints, где он появляется. Это можно сделать с помощью map:

removePointFromShipList :: Point -> [ShipPoints] -> [ShipPoints]
removePointFromShipList p lst = map (removePointFromShip p) lst

. Используется вспомогательная функция:

removePointFromShip :: Point -> ShipPoints -> ShipPoints

, которая удаляет Point из указанного c ShipPoints. Эта вспомогательная функция может быть определена с помощью фильтра:

removePointFromShip p shp = filter (/= p) shp

Я думаю, что вышеупомянутые функции просты и не нуждаются в улучшении, но поскольку Haskell программисты не могут уйти хорошо Достаточно в одиночку, большинство (в том числе и я) попытаются изменить это. Не стесняйтесь игнорировать эту часть или просто просмотреть ее ради развлечения.

В любом случае, многие Haskellers переместят функцию removePointFromShip в предложение where и, возможно, сократят имена:

removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p lst = map removePoint' lst
  where removePoint' shp = filter (/= p) shp

Тогда многие люди поймут, что если у вас есть f x = blah blah blah x, вы можете заменить это на f = blah blah blah (процесс, известный как eta-Reduction). Обе основные и вспомогательные функции могут быть сокращены на eta следующим образом:

removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p = map removePoint'
  where removePoint' = filter (/= p)

Теперь нет смысла иметь предложение where так:

removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p = map (filter (/= p))

Это очень хорошо и большинство людей остановится здесь. По-настоящему сумасшедший признал бы возможность превратить это в «бессмысленную» форму, написав:

removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint = map . filter . (/=)

(Технически, это не идентично предыдущей версии, но это нормально, пока p /= q всегда совпадает с q /= p.) Теперь это выглядит действительно умно, но никто не может понять это, просто взглянув на него, поэтому мы должны добавить комментарий:

-- Remove Point everywhere it appears in [ShipPoints]
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint = map . filter . (/=)

Удивительно!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...