Haskell-Lambda函数——两个看似等价的函数,一个有效,另一个错误



此Lambda函数返回1:

  (x y -> 1) 1 p

其中p=(\xy->1)

好吧,这对我来说很有意义——Lambda函数返回1,与它的参数无关。

现在,这个Lambda函数生成一个错误(无限类型错误):

  (x y -> x y x) p 1

这对我来说没有意义。如果这个函数应用于这里的参数,则是用p代替x,用1代替y的结果:

  p 1 p

用其定义替换第一个p:

  (x y -> 1) 1 p

嘿!这与上面的相同,返回1。

问题:为什么(\xy->1)1 p成功,而(\xy->x y-x)p 1失败?

/收到

使用以下表达式(其中两个p必须具有相同的类型,因为如果不显式指定多态类型,lambda变量就不能同时具有两个类型):

p 1 p

在这种情况下,p的类型是什么?为了简单起见,假设1Int。让我们从一个简单的尝试开始:

(p :: Int -> ? -> Int) 1 p

那么,问号是什么呢?它必须是p的类型,因为这就是你给出的论点。因此:

(p :: Int -> (Int -> ? -> Int) -> Int) 1 p

同样的问题,同样的解决方案:

(p :: Int -> (Int -> (Int -> ? -> Int) -> Int) -> Int) 1 p

现在你明白了为什么我们有无限类型的问题:虽然我们不需要来知道p的第二个参数的类型;因为Haskell类型系统是严格的(又称不懒惰),所以它无论如何都需要找出类型,并被这种无限类型所困扰。

此代码成功:

(x y -> 1) 1 p

因为左边的函数可以具有与p不同的类型,因为它们是不同的函数,所以我们在尝试统一类型时不会遇到相同的问题:

(( x y -> 1) :: a -> b -> Int) 1 (p :: c -> d -> Int)

除了dflemstr所说的,lamba的类型永远不会取决于它所应用的值。类型检查器将首先找到lambda的类型,然后检查它是否正确应用。

因此,您认为在beta替换后表达式是相同的论点是无关紧要的:lambda必须是孤立的良好类型。

最新更新