Haskell Lambda函数 - 两个看似相同的函数,一个是有效的,另一个是错误的

时间:2012-03-04 19:56:38

标签: haskell anonymous-function lambda

此Lambda函数返回1:

  (\x y -> 1) 1 p

其中p =(\ x y - > 1)

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

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

  (\x y -> x y x) p 1

这对我没有意义。如果将此函数应用于参数,则将p替换为x,将x替换为y:

  p 1 p

按照定义替换第一个p:

  (\x y -> 1) 1 p

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

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

/罗杰

2 个答案:

答案 0 :(得分:20)

使用此表达式(其中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)

答案 1 :(得分:5)

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

因此,你认为在beta替换之后表达式是相同的是无关紧要的:lambda必须是单独输入的。