I came across this function
iter p f x = if (p x) then x else (iter p f (f x))
and I thought I'd give a go at defining the polymorphic types myself to understand the concept.
My thought was the following:
The function takes 3 parameters, so we have t1 -> t2 -> t3 -> T
p
is being used inside the if condition so it must return a bool
, therefore t1 = a -> Bool
f
is also the same type as p
because it is passed as an argument in the else block, therefore t2 = a -> Bool
x is being used inside the if condition so it must return a bool, therefore t1 = a -> Bool
But when i checked the type in the ghci, the type they gave me was
iter :: (t -> Bool) -> (t -> t) -> t -> t
Can someone please explain the reasoning behind this.
Thanks
The function takes 3 parameters, so we have t1 -> t2 -> t3 -> T
This is correct as a starting point.
p is being used inside the if condition so it must return a bool, therefore t1 = a -> Bool
Correct.
f is also the same type as p because it is passed as an argument in the else block, therefore t2 = a -> Bool
Incorrect. f
is never used in the same way as p
. In the else block f
is being applied to x
and the result passed as the last argument to iter
. From that we know f x
must be the same type as x
so f :: a -> a
.
x is being used inside the if condition so it must return a bool, therefore t1 = a -> Bool
Incorrect. In the if condition x
is being used only as an argument to p
. You established above p :: a -> Bool
. Therefore x :: a
.
But when i checked the type in the ghci, the type they gave me was
iter :: (t -> Bool) -> (t -> t) -> t -> t
Correct. You could also write this replacing t
with a
to be consistent in the notation - we used a
above:
iter :: (a -> Bool) -> (a -> a) -> a -> a