Функция библиотеки для создания функции с собой n раз

Есть ли в Haskell библиотечная функция для создания функции с собой n раз?

Например, у меня есть эта функция:

func :: a -> a

и я хочу сделать это:

func . func . func . func . func . func , ... 

(до n раз, где n известно только во время выполнения).

Обратите внимание, что функция итерации не подходит для того, что я делаю, так как мне не нужны промежуточные результаты.

Ответ 1

Решение iterate прекрасное, или вам может понравиться это: состав n копий f равен foldr (.) id (replicate n f).

Ответ 2

\xs n -> iterate func xs !! n

(xs - начальное значение, n - сколько раз применить func)

Я не знаю почему, но я чувствую, что iterate - это то, что люди постоянно не изучают при изучении Хаскелла.

Если вам не нравится !!, вы можете использовать zip и lookup в качестве альтернативы. (некоторым людям/группам/инструментам не нравятся функции, которые в некоторых случаях вызывают "ошибку", я не утверждаю, что поиск в этих случаях лучше)

lookup n . zip [0..] . iterate func

ОБНОВЛЕНИЕ: Хорошо, поэтому я удалил, а затем удалил, потому что я согласен с другим ответчиком - вы не должны сбрасывать со счетов использование итерации только потому, что оно дает вам больше, чем вам нужно.

Ответ 3

Я не знаю, почему вы говорите, что iterate не подходит. Он идеально подходит для этой цели. (!! n) . iterate func является композицией n копий func.

(Кто-то отправил ответ, похожий на приведенный выше код, но он, похоже, удалил его.)

Ответ 4

(\n -> appEndo . mconcat . replicate n . Endo) n f x

Ответ 5

Я начинаю в Haskell, в настоящее время на пятой главе ( "Функции более высокого порядка" ) Учите вас в Haskell For Great Good! поэтому я еще не знаком с функциями, показанными в предыдущих ответах. Учитывая то, что я понимаю до сих пор, я бы сделал это следующим образом:

applyNTimes :: Int -> (a -> a) -> a -> a
applyNTimes n f x 
    | n == 0        = x
    | otherwise     = f (applyNTimes (n-1) f x)

Ответ 6

\n -> appEndo . foldMap Endo . replicate n

Ответ 7

Вариант ответа trinithis с помощью пакета newtype, просто для удовольствия:

(\n f -> under Endo (mconcat . replicate n) f)

Или без точек:

under Endo . (mconcat .) . replicate

Ответ 8

Вот версия, которая имеет сложность O (log n) вместо O (n) (для построения функции, а не для ее применения):

composeN 0 f = id
composeN n f
    | even n = g
    | odd  n = f . g
    where g = g' . g'
          g' = composeN (n 'div' 2) f

Ответ 9

Другое решение с использованием foldr:

\n → flip (foldr ($)). replicate n

Ответ 10

iterate (f .) id !! n

или

iterate (f .) f !! (n-1)

в зависимости от того, разрешено ли n == 0.