Мы начинаем с переписывания positions
как
positions x xs = map (\(_, i) -> i) . filter (\(y, _) -> y == x) $ zip xs [0..]
и переписываем find
как
find k t = map (\(_, v) -> v) . filter (\(m, _) -> m == k) $ t
-- or,
find x = map (\(_, i) -> i) . filter (\(y, _) -> y == x)
, а затем просто замечаем, что две части кода точно одинаковы (после переименования переменных):
positions x xs = find x $ zip xs [0..]
find
принимает только списки пар , затем фильтрует их и извлекает второй компонент;вам придется использовать что-то (например, zip
), чтобы получить пары для обработки find
. нет пути вокруг него.
Конечно, positions
также можно кодировать без части zip
(вместо этого, например, используя mapAccumL
), но тогда это не такнужно find
:
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
positions :: (Eq a) => a -> [a] -> [Int]
positions x = concat . snd . mapAccumL g 0
where
g acc y = (acc+1, [acc | y == x])
Мы могли бы сделать так, чтобы список получился, как и ожидалось, к find
, искусственно, но это потребует много работы и просто будет повторной реализациейzip
с перечислительной частью (то есть, не самой find
), в любом случае.