Карта Haskell, но удаляет элементы, которые не соответствуют условию - PullRequest
0 голосов
/ 16 февраля 2019

Функция должна взять список кортежей и вернуть те, которые имеют сумму> 5

Допустим, у меня есть следующий код:

fn :: [(Int, Int)] -> [(Int, Int)]

fn tuples = map (\(x,y) -> if (x + y) > 5 then (x,y) else (0,0)) tuples

fn [(3,4), (4,4), (0,1)] возвращает [(3,4),(4,4),(0,0)] но на самом деле я просто хочу, чтобы он возвратил [(3,4),(4,4)]

Возможно ли это в haskell, все еще следуя сигнатуре типа?

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Немного странный вопрос, но после комментария

Я не вижу понятия «пустой кортеж» в haskell

Я думаю, я вижу, где вы 'приходит из.На самом деле в Haskell есть «пустые кортежи»: тип блока () - это тип «кортежей с нулевыми элементами».Так что вы думаете о

fn tuples = map (\(x,y) -> if x + y > 5 then (x,y) else ()) tuples

Но это не сработает, потому что () это другой тип от (Int,Int).Все элементы списка должны иметь одинаковый тип.Даже если бы это сработало, как в динамических типах, результат fn [(3,4), (4,4), (0,1)] на самом деле был бы [(3,4), (4,4), ()].Т.е. вы все равно получите три элемента, только один из них будет «скучным».

map фактически обеспечивает гарантию, что никогда не изменит количество элементов в списке, только значения ихэлементы.Так что, если вы хотите , вам нужно использовать другую функцию.Наиболее близким к вашему подходу будет concatMap:

fn tuples = concatMap (\(x,y) -> if x + y > 5 then [(x,y)] else []) tuples

То, что здесь происходит, также может быть описано в два этапа:

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

Итак [(3,4), (4,4), (0,1)] -> [[(3,4)], [(4,4)], []] -> [(3,4), (4,4)].

На самом деле, здесь вообще нет необходимости использовать шаг отображения - элементы сохраняются такими, какие они есть в конечном итоге, поэтому filter - это инструмент для использования.

0 голосов
/ 16 февраля 2019

Вы запрашиваете mapMaybe :

mapMaybe :: (a -> Maybe b) -> [a] -> [b]

base Data.Maybe

Функция mapMaybe является версией map, который может выбрасывать элементы.В частности, функциональный аргумент возвращает что-то типа Maybe b.Если это Nothing, ни один элемент не добавляется в список результатов.Если это Just b, то b включается в список результатов.

Наименьшее изменение для использования его в вашем коде будет:

import Data.Maybe

fn :: [(Int, Int)] -> [(Int, Int)]
fn tuples = mapMaybe (\(x,y) -> if (x + y) > 5 then Just (x,y) else Nothing) tuples

Однако в этомконкретный случай, вы на самом деле не трансформируетесь, вы просто удаляете.Если вы не планируете добавлять преобразование позже, filter более подходит:

fn = filter (\(x,y) -> x+y > 5)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...