tags:

views:

246

answers:

4

Is there a library function available in Haskell to compose a function with itself n times?

For example I have this function:

func :: a -> a

and I want to do this:

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

(up to n times, where n is only known at runtime).

Note that the iterate function would not be appropriate for what I am doing, since I do not care about any intermediate results.

+9  A: 
\xs n -> iterate func xs !! n

I don't know why, but I feel like iterate is something people aren't consistently exposed to when learning Haskell.

If you don't like !! then you could use zip and lookup as an alternative. (some people/groups/tools don't like functions that call "error" in certain cases, I'm not claiming lookup is any better in these cases)

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

EDIT: Ok, so I deleted then undeleted because I agree with the other answerer - you shouldn't discount use of iterate just because it gives you more than you need.

TomMD
For what it's worth, since `iterate` guarantees an infinite list, I would use `(!!)` or `genericIndex` over using `lookup` with `zip`.
trinithis
Yes, that's what I was getting out about `lookup` and `zip` not being any better in these cases. `(!!)` has a stigma much like `head` does (or, that's my impression)
TomMD
Yes, it's a well-deserved stigma in my opinion too, but all it really means is that you have to be careful about using it in cases where it might not apply - not that you should never use it. As trinithis points out, in this case it cannot go wrong except when passed a negative index. Incidentally !! is actually a demonstrably better choice than lookup here: lookup and zip will loop forever on a negative index, looking for a result that isn't there, but !! will fail immediately because it knows indices can't be negative.
mokus
+7  A: 

I do not know why you say that iterate is not appropriate. It is perfectly suitable for this purpose. (!! n) . iterate func is the composition of n copies of func.

(Someone had posted an answer similar to the above code, but he/she seems to have deleted it.)

Tsuyoshi Ito
+14  A: 

The iterate solution is fine, or you might like this one: the composition of n copies of f is foldr (.) id (replicate n f).

Reid Barton
I like this because it also works with n==0.
John
@John The other solutions (`iterate` with `!!` or `lookup . zip`) also work with n == 0. Look at the [definition of iterate](http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/src/GHC-List.html#iterate) and you'll see it starts the list with the base case.
TomMD
@TomMD you're right, my mistake. I was thinking of a different definition using `iterate`, which isn't nearly as nice as what you provided.
John
+4  A: 

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

trinithis