此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失败?
/罗杰
答案 0 :(得分:20)
使用此表达式(其中p
必须具有相同的类型,因为如果未明确指定多态类型,则lambda变量不能同时具有两种类型):
p 1 p
此上下文中p
的类型是什么?假设1
为Int
,为简单起见。让我们从一个简单的尝试开始:
(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必须是单独输入的。