-2

I'm trying to create an iterative function that takes in an 'a => 'a function, and a natural number which indicates how many times to iterate this function. It will output another 'a => 'a function. Example input:

let func: int => int = num => x-2;

iterate(func, 3) would output func(func(func())) or x-6

However, I have this code

let rec iterate: ('a => 'a, int) => ('a => 'a) = (f, n) =>
switch(n){
    | 1 => f
    | x when x > 1 => f(iterate(f, n-1))
};

and it is giving me this error right under f(iterate(f, n-1))

This expression has type 'a => 'b but an expression was expected of type ('a => 'b, 'a) => 'b.

Edit: I believe it has something to do with the type signature in the first line being read by the compiler as ('a => 'a, int, 'a) => 'a for some reason and I have no clue why it would be reading it like that.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 5
    Please don't make more work for others by vandalizing your posts. By posting on the Stack Exchange (SE) network, you've granted a non-revocable right, under a [CC BY-SA license](//creativecommons.org/licenses/by-sa/4.0), for SE to distribute the content (i.e. regardless of your future choices). By SE policy, the non-vandalized version is distributed. Thus, any vandalism will be reverted. Please see: [How does deleting work? …](//meta.stackexchange.com/q/5221). If permitted to delete, there's a "delete" button below the post, on the left, but it's only in browsers, not the mobile app. – Makyen Jan 04 '20 at 22:53
  • 5
    You are not allowed to substantially change your question. If you have a follow-up question, ask a new question. – Cody Gray - on strike Jan 05 '20 at 02:34

1 Answers1

0

In the second branch you give f the result of calling iterate recursively, which according to your type annotation returns a function. Therefore 'a must be a function 'a => 'b. Also, if you return the result of calling f directly, that result must also be a function since that's what iterate should return.

So you cannot return the result of applying f directly. You have to return a function that calls f with the value given to it, then passes its return value to the function returned from a recursive call to iterate (or the other way around), and then returns that value.

glennsl
  • 28,186
  • 12
  • 57
  • 75
  • You don't need to tell it what to operate on. And the type signature is fine. Because of currying, what the compiler shows you is an equivalent type signature. The only thing wrong with your code is the last branch. – glennsl Dec 11 '19 at 00:44
  • Try adding `'a.` to the type signature. It'll make `'a` explicitly polymorphic which gives you a better error message: `'a. ('a => 'a, int) => ('a => 'a)` – glennsl Dec 11 '19 at 00:46
  • `x => f(f(x))` has the same type signature as `f`, but calls it twice. `x => f(f(f(x)))` calls it three times. Now you just have to figure out how to call `iterate` recursively in there. – glennsl Dec 11 '19 at 09:29