Фильтр списка кортежей с самой длинной строкой - PullRequest
0 голосов
/ 13 февраля 2019

Я новичок в Haskell и пытаюсь отфильтровать список кортежей, используя длину 2-го элемента (String) и возвращая правильный кортеж, если он вообще есть ..

Prelude> let lst = [(a,rr), (b,rr), (c, rrr), (d, rrrr)]

Prelude> filter ((>4).(length snd)) lst

[d, rrrr)]

Ошибка при попытке его выполнить, длина имеет слишком много аргументов ..

Может кто-нибудь мне помочь.Большое спасибо!

Ответы [ 2 ]

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

Исправление великое, но остается проблема с необходимостью знать самую длинную длину строки в функции, чтобы соответствовать или превышать ее.Что если вы не знаете самую длинную длину поля и не можете закодировать ее в своей функции?Функция lf выплевывает длину самой длинной строки.Я действительно думаю, что лямбда в предикате фильтра более понятна.

lf должен отслеживать самую длинную строку, чтобы он не мог передавать кортежи, а только отдельные значения.

ls = [('a',"rr"), ('b',"rr"), ('c', "rrr"), ('d', "rrrr")]
lf = (\a b -> if (length $ snd b) > a then (length $ snd b) else a)
filter (\t -> (length $ snd t) == (foldl lf 0 ls)) ls

[( 'd', "рррр")]

0 голосов
/ 14 февраля 2019
filter ((>4).(length snd)) lst

Похоже, у вас есть правильная идея с этим, но, как вы заметили, она не компилируется.Хотя, когда я пытаюсь это сделать, ошибка отличается от той, о которой вы упомянули, что у length слишком много аргументов - вы указали здесь один аргумент, который является правильным числом.Тем не менее, аргумент, который вы указали, является функцией (snd, которая дает вам второй элемент пары), и он ожидает список - поскольку нет возможности рассматривать функцию как список, компилятор отклоняетэто бессмысленно.(Даже если бы это не было проблемой, length snd приведет к Int, и вы не можете использовать это в качестве аргумента оператора ., которому нужна функция с любой стороны. И это то, что GHCна самом деле жалуется, когда я пытаюсь запустить ваш код: Couldn't match expected type '([Char], [Char]) -> Integer' with actual type 'Int' In the second argument of '(.)', namely '(length snd)')

@ WillemVanOnsem уже показал вам, как это исправить, поэтому давайте посмотрим на это.Он действительно очень похож на ваш:

filter ((>4) . length . snd)) lst

Оператор ., как вы, кажется, знаете, применяет сначала функцию справа, а затем функцию слева от результата.Таким образом, выражение (>4) . length . snd означает, что для заданной пары взять второй элемент, затем взять его длину (предполагается, что это список, или он не скомпилируется), а затем проверить, больше ли полученное число больше 4 или нет.Другими словами, (>4) . length . snd) - это предикат типа (a, [b]) -> Bool, который сообщает вам, содержит ли список во втором слоте пары более 4 элементов или нет.[Термин «предикат» означает просто любую функцию, которая возвращает Bool - это тест, применяемый к элементам интересующего вас типа, используемым в filter и многих связанных функциях.] И это, конечно, точното, к чему вы стремитесь.

Итак, подведем итог: единственное различие между вашим ответом и правильным ответом состоит в том, что между length snd (предоставление функции snd в качестве аргумента length, чтобессмысленно) и length . snd (функция, заданная сначала применением snd, затем length к его результату).Они могут выглядеть одинаково, но на самом деле они имеют в виду совершенно разные вещи.

Я уверен, что, немного потренировавшись, вы сможете сами сделать такие вещи правильно и понять, что говорит GHCвы, когда он выдает ошибку компиляции.

(PS: ваш код на самом деле дает сбой, потому что a, rr и т. д. - это переменные, которые вы не привязали ни к каким значениям. I 'мы предположили, что все они должны быть строками, особенно если вы взяли длину значений r..r - в этом случае их необходимо заключить в двойные кавычки: ("a", "rr") и т. д.

...