Я относительно новичок в haskell, но в своих поисках я не смог найти простой способ условно свернуть список. т. е. когда элемент удовлетворяет условию (например, filter
), чтобы свернуть этот элемент с помощью функции (например, foldr
и foldl
).
Мой обходной путь состоял в том, чтобы написать следующую вспомогательную функцию, а затем применить map
, чтобы изменить результирующий список пар в соответствии с моей ситуацией.
-- This function returns tuples containing the elements which
-- satisfy `cond` folded right, adding 1 to the second value
-- in each pair. (`snd` pair starts at 0)
-- Condition takes a single value (similar to `filter`)
-- NOTE: list cannot end with token
foldrOn cond list =
if (length list) > 0 then
if cond (head list) then
do
let tmp = foldrOn cond (tail list)
(fst (head tmp), snd (head tmp) + 1) : (tail tmp)
-- fold token into char after it
else
(head list, 0) : (foldrOn cond (tail list))
-- don't fold token
else
[] -- base case len list = 0
foldlOn cond list = ...
Например, вариант использования может быть чем-то вроде желания удалить нули в следующих списках, но помнить, сколько было удалено между каждым значением.
-- the second value in each resultant pair represents the number of
-- zeroes preceding the corresponding first value in the original list.
foldrOn (== 0) [1,0,0,0,0,0,1,0,0,0,1] -- [(1,0),(1,5),(1,3)]
foldrOn (== 0) [1,0,0,12,0,13] -- [(1,0),(12,2),(13,1)]
Есть ли лучший способ сделать это? Кроме того, можно ли это сделать более оптимально?
foldrOn
не получает аргумент двоичной функции, поэтому на самом деле это неfold
. Пожалуйста, покажите желаемый результат вашего варианта использования. - person n. 1.8e9-where's-my-share m.   schedule 23.12.2020foldrOn (== 0)
с обоими входными данными из вашего примера, но я не понимаю, как фактическое поведение согласуется с заявленной целью. - person Mark Seemann   schedule 23.12.2020do
.do { let {a=b} ; c }
полностью совпадает сlet {a=b} in do c
, аdo c
— это простоc
, когдаc
— это всего лишь одно выражение. - person Will Ness   schedule 23.12.2020head
иtail
... почти никогда. Я знаю, что это Haskell, но читается как Lisp. Вычислятьlength
списка и проверять, равен ли он нулю, (практически) никогда не бывает хорошей идеей. Обычно вы хотите либо использовать стандартное свертывание/обход, либо сопоставление с шаблоном в списке, чтобы определить, пуст ли он, и, если это не так, разложить его на начало и конец. Почти во всех других случаях вы должны использоватьnull
, чтобы проверить, пуст ли список. - person dfeuer   schedule 23.12.2020