Написание функции высокого порядка для захвата общего шаблона haskell

f1 [] = 1
f1 (x:xs) = x * f1 xs

f2 [] = 0
f2 (x:xs) = 1 + f2 xs

f3 [] = 0
f3 (x:xs) = x + f3 xs

f4 [] = []
f4 (x:xs) = x ++ f4 xs

Все они имеют общее поведение, как точно я могу определить шаблон и написать функцию высокого порядка для его захвата?

Ответ 1

Все * ваши функции имеют форму:

fn [] = P_0
fn (x:xs) = P_1 x (fn xs)

Где P_0 и P_1 - некоторые константы. Я назову P_0 zero, а P_1 combine и добавить их в функцию:

-- P_0  P_1     list   = result
fn zero _       []     = zero
fn zero combine (x:xs) = combine x (fn zero combine xs)

Мы идем. Теперь мы имеем f1 = fn 1 (*), f3 = fn 0 (+) и f4 = fn [] (++). f2 немного странно, но вы можете это f2 = fn 0 (\_ b → b+1): f2 = fn 0 (\_ b → b+1).

Задавая GHCi тип дает нам, что fn :: b → (a → b → b) → [a] → b, а Hoogling показывает, что эта функция fn фактически является функцией foldr:

foldr :: (a -> b -> b) -> b -> [a] -> b
--       ^combine         ^zero

Итак, вы идете: складки, или особенно правые складки (r в foldr означает право) - это общий шаблон, который вы ищете.

Кстати, есть и левые складки. Я оставлю вас, чтобы попытаться выяснить, что это может быть. Hoogle также может помочь вам здесь.

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


* Это может выглядеть странно для f2 (x:xs) = 1 + f2 xs, поскольку в результате не участвует x, но это как раз тот случай, когда P_1 ab = 1 + b, который по-прежнему технически одинаковый форма.

Ответ 2

Похоже, вы можете использовать foldr для представления всех из них.

foldr (*) 1 [1,2,3]  --f1

foldr (\_ a-> 1 + a) 0 [1,2,3]  --f2

foldr (+) 0 [1,2,3]  --f3

foldr (++) [] ["a","b","c"]  --f4

Им всем нужен список, значение init и оператор. Все они применяют оператор справа налево: например, f1 [1,2,3] = 1*2*(3*1) Таким образом, вы можете использовать foldr для параметризации оператора и значения init.