Применить функцию несколько раз в Haskell

Изучайте Haskell во благо (раздел «Функции высшего порядка», подраздел "Некоторый высший порядок в порядке") описывает пример функции applyTwice, которая дважды вызывает функцию для аргумента:

applyTwice :: (a -> a) -> a -> a  
applyTwice f x = f (f x)

Но мне нужна функция, которая применяет некоторую функцию к некоторому аргументу произвольное количество раз. Например, applyN 3 f x будет эквивалентно f $ f $ f x. Как бы я написал функцию повторного применения в Haskell? Пожалуйста, опубликуйте любые возможные решения, используя рекурсию, функции более высокого порядка или что-то еще.


person Mirzhan Irkegulov    schedule 24.03.2014    source источник


Ответы (3)


Я всегда делал что-то вроде iterate f x !! n.

person Emil    schedule 24.03.2014

Вам нужно будет выполнить рекурсивную функцию. Очевидным случаем будет то, что когда вы применяете функцию 0 раз, это будет похоже на то, что вы не изменяете ввод. Рекурсивность будет исходить из того, что applyN n f x == f (applyN (n -1) f x или из-за того, что композиция функции ассоциативна applyN n f x == apply (n - 1) f (f x). Второй вариант приводит к лучшей производительности, потому что он будет хвостовой рекурсией.

applyN :: Int n => n -> (a -> a) -> a -> a
applyN 0 _ x = x
applyN n f x = applyN (n - 1) f (f x)
person Luc DUZAN    schedule 24.03.2014

applyN = (foldr (.) id.) . replicate

-->>
applyN 0 f = id
applyN 1 f = f
applyN 2 f = (f.f)
-- ...

Или просто используйте iterate, как уже было сказано ранее. Единственная реальная разница заключается в том, что при использовании iterate вы получите исключение, если укажете отрицательное n, тогда как в этом решении вы получите id. Если это случай, который правдоподобно может произойти для вашего варианта использования, вам следует подумать, какое поведение вам больше нравится.

person Cubic    schedule 24.03.2014