Haskell:确定函数类型

Hyb*_*tem 0 haskell functional-programming

在学习功能编程考试时,我从之前的测试中发现了以下问题:

t2 = (\x -> \y -> \z -> (x y, x (x z)))

t3 = t2 (take 3 . reverse) mnr mnr
Run Code Online (Sandbox Code Playgroud)

对于t2,要求它确定语句的最一般类型.答案似乎是:

(a -> a) -> a -> a -> (a,a)
Run Code Online (Sandbox Code Playgroud)

我可以通过在WinHugs中输入声明来找到答案,但是如何找到答案呢?我从之前的帖子中了解到它与lambda函数有关,但除此之外我无法解释这里发生了什么.

然后问题的第二部分(t3)将两个函数应用于变量mnr的两个实例.对于mnr = [0,1,2,3,4,5,6],这会导致:

([6,5,4],[4,5,6])
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?函数take和reverse是清楚的,但它们如何应用于t2中的lambda函数?

ger*_*ter 6

让我们从中间开始,结果.

(x y, x (x z))
Run Code Online (Sandbox Code Playgroud)

因为x正在应用于事物(y,zx z),我们知道它具有(a -> ?)问号代表未知类型的类型.现在,结果x传递给xin x (x z),所以它的输入类型必须是它的输出类型:

x :: a -> a
Run Code Online (Sandbox Code Playgroud)

现在,x应用于yz,因此它们都必须是类型a.x y并且x (x z)也都是类型a(因为它是x返回类型),所以t2返回类型的东西(a, a).

与它的参数的类型一起把这个(x,y,和z),我们得到的是已经键入

(a -> a) -- x's type
-> a -- y's type
-> a -- z's type
-> (a, a) -- the result type
Run Code Online (Sandbox Code Playgroud)

对于你的第二个问题,让我们首先看看t2与定义中的变量有什么关系.第一个参数是x,所以在这种情况下

x = (take 3 . reverse)
Run Code Online (Sandbox Code Playgroud)

下一个参数是y,所以

y = mnr
Run Code Online (Sandbox Code Playgroud)

同样对于z,

z = mnr
Run Code Online (Sandbox Code Playgroud)

结果将是(x y, x (x z)),所以让我们评估一下

(x y, x (x z))
= ((take 3 . reverse) mnr, (take 3 . reverse) ((take 3 . reverse) mnr))
= (take 3 (reverse mnr), take 3 (reverse (take 3 (reverse mnr))))
Run Code Online (Sandbox Code Playgroud)

有了这个特例mnr = [0,1,2,3,4,5,6],我们得到了

= (take 3 (reverse [0,1,2,3,4,5,6]), take 3 (reverse (take 3 (reverse [0,1,2,3,4,5,6]))))
= (take 3 [6,5,4,3,2,1,0], take 3 (reverse (take 3 [6,5,4,3,2,1,0])))
= ([6,5,4], take 3 (reverse [6,5,4]))
= ([6,5,4], take 3 [4,5,6])
= ([6,5,4], [4,5,6])
Run Code Online (Sandbox Code Playgroud)