Haskell 中的多态类型

Polymorphic types in Haskell

我遇到了这个函数

iter p f x = if (p x) then x else (iter p f (f x))

我想我应该自己定义多态类型来理解这个概念。

我的想法如下:

函数有3个参数,所以我们有t1 -> t2 -> t3 -> T

  1. p 在 if 条件中使用,因此它必须 return 一个 bool,因此 t1 = a -> Bool

  2. f 也是与 p 相同的类型,因为它在 else 块中作为参数传递,因此 t2 = a -> Bool

  3. x 在 if 条件中使用,所以它必须 return 一个布尔值,因此 t1 = a -> Bool

但是当我检查ghci中的类型时,他们给我的类型是

iter :: (t -> Bool) -> (t -> t) -> t -> t

谁能解释一下这背后的原因。

谢谢

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

不正确。 f 永远不会像 p 那样使用。在 else 块中,f 被应用于 x,结果作为最后一个参数传递给 iter。由此我们知道 f x 必须与 x 的类型相同,所以 f :: a -> a.

x is being used inside the if condition so it must return a bool, therefore t1 = a -> Bool

不正确。在 if 条件中 x 仅用作 p 的参数。你在上面建立了p :: a -> Bool。因此x :: a.

But when i checked the type in the ghci, the type they gave me was

iter :: (t -> Bool) -> (t -> t) -> t -> t

正确。您也可以将 t 替换为 a 以在符号中保持一致 - 我们在上面使用了 a

iter :: (a -> Bool) -> (a -> a) -> a -> a

Let's evaluate it again:

iter p f x = if (p x) then x else (iter p f (f x))

iter takes three parameters (well technically speaking every function takes one parameter, but let's skip the details). So it has indeed a type t1 -> t2 -> t3 -> t.

Now in the if-then-else statement, we see (p x) this means that p x has to evaluate to a boolean. So that means that:

t1 ~ t3 -> Bool

Next we see x in the then statement. This may strike as non-important, but it is: it means that the output type t is the same as that of t3, so:

t3 ~ t

Now that means we already derived that iter has the type:

iter :: (t3 -> Bool) -> t2 -> t3 -> t3

Now we see in the else statement the call:

iter p f (f x)

So that means that f is a function f :: t4 -> t5. Since it takes x as input, its input type should be t3, and since the result of (f x) is passed to an iter function (that is not per se the same "grounded" iter function). So we have to inspect the call:

iter :: (u3 -> Bool) -> u2 -> u3 -> u3  -- call

Now since we call it with iter p f (f x) we definitely know that u3 ~ t3: because p has type t3 -> Bool. So it grounds further to:

iter :: (t3 -> Bool) -> u2 -> t3 -> t3  -- call

Sine (f x) is used as third argument, we know that the type of the result of f x should be t3 as well. So f has type f :: t3 -> t3. So we conclude that iter has the type:

iter :: (t3 -> Bool) -> (t3 -> t3) -> t3 -> t3