1

我遇到了这个功能

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

我想我会尝试自己定义多态类型以理解这个概念。

我的想法如下:

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

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

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

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

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

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

有人可以解释一下这背后的原因。

谢谢

4

2 回答 2

5

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

这作为一个起点是正确的。

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

正确的。

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

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

x 在 if 条件中使用,因此它必须返回一个 bool,因此 t1 = a -> Bool

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

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

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

正确的。您也可以将其替换为ta符号一致 - 我们在a上面使用过:

iter :: (a -> Bool) -> (a -> a) -> a -> a
于 2017-08-03T14:03:48.973 回答
1

让我们再次评估它:

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

iter接受三个参数(从技术上讲,每个函数都接受一个参数,但让我们跳过细节)。所以它确实有一个 type t1 -> t2 -> t3 -> t

现在在if--语句中thenelse我们看到(p x)这意味着p x必须评估为布尔值。这意味着:

t1 ~ t3 -> Bool

接下来我们xthen声明中看到。这可能并不重要,但它是:这意味着输出类型t与 的相同t3,所以:

t3 ~ t

现在这意味着我们已经派生了iter具有以下类型的:

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

现在我们在else语句中看到调用:

iter p f (f x)

所以这意味着那f是一个函数f :: t4 -> t5。由于它x作为输入,它的输入类型应该是t3,并且由于结果(f x)被传递给一个iter函数(这本身不是相同的“接地”iter函数)。所以我们必须检查调用:

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

现在,既然我们用 with 调用它,iter p f (f x)我们肯定知道u3 ~ t3:因为phas type t3 -> Bool。因此,它进一步基于:

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

正弦(f x)用作第三个参数,我们知道结果的类型也f x应该是t3f类型也是如此f :: t3 -> t3。因此我们得出结论,iter 具有以下类型:

iter :: (t3 -> Bool) -> (t3 -> t3) -> t3 -> t3
于 2017-08-03T14:14:26.547 回答