Мой подход заключается в
- Решить проблему для элемента в списке, на который вы в данный момент смотрите (
x
или my_pattern
).Это означает создание одного или нескольких новых списков. - Решите проблему для остальной части списка (
xs
).Это вернет вам список списков ([[C]]
). - Объедините два решения.Если у вас есть несколько списков, созданных на шаге 1, каждый из этих списков (
[C]
) объединится с каждым списком (также [C]
) в списке списков ([[C]]
) с шага 2.
У меня есть два возможных подхода.
Мне не ясно, какую помощь вы ищете, поэтому я оставил свои ответы несколько «свободными от спойлеров».Если вам это нужно, попросите разъяснений или дополнительных подробностей.
Понимание списка
Не углубляясь в сорняки классов типов Applicative
или Traversable
, вы можете достичь желаемого с помощью спискапонимание.
Давайте рассмотрим случай, когда ваш шаблон соответствует.Я хотел бы написать понимание списка следующим образом:
[ x ++ y | x <- _, y <- _] :: [[C]]
-- this means
-- x :: [C]
-- y :: [C]
-- _ :: [[C]]
Это понимание списка создает список списков.x
- это то, что предваряется, поэтому было бы целесообразно, чтобы оно исходило от применения функций f1
и f2
.y
- это конец каждого результирующего списка.Я оставлю вас, чтобы выяснить, что это может быть.
Несоответствующий случай проще, чем этот, и может быть записан как
[ x : y | y <- _] :: [[C]]
-- note that x is not local to the list comprehension
-- y :: [C]
-- _ :: [[C]]
, хотя это действительно особый случайиз приведенного выше понимания списка.
Аппликативный
Еще один способ решения этой проблемы - использование Applicative
экземпляра [a]
.
Давайте рассмотрим функцию (<*>)
в списке Applicative
instance.
-- this is the type when specialized to lists
(<*>) :: [a -> b] -> [a] -> [b]
Эта функция имеет своего рода странную сигнатуру типа.Он принимает список функций и список, а затем возвращает вам другой список.Он имеет эффект применения каждой функции a -> b
к каждому элементу [a]
по порядку.
>>> [(+1), (+2)] <*> [1,2,3]
-- [2,3,4] comes from (+1)
-- [3,4,5] comes from (+2)
[2,3,4,3,4,5]
Мы хотим получить [[C]]
, а не [C]
, поэтому, если мы хотим использовать(<*>)
мы можем специализировать его тип больше на
(<*>) :: [a -> [C]] -> [a] -> [[C]]
Чтобы избежать путаницы, я рекомендую выбрать a = [C]
, что дает
(<*>) :: [[C] -> [C]] -> [[C]] -> [[C]]
Ваш список функций должен предшествовать правильномуэлементы на списки, которые вы генерируете.Вторым аргументом должны быть списки, возвращаемые рекурсивным вызовом.