只是想看看像这样的一些lambda表达式的类型:
:t \x -> (\y -> x y)
\x -> (\y -> x y) :: (t1 -> t2) -> t1 -> t2
这里的类型不应该是t1->(t2->t1->t2)
吗?
同样
:t \x -> (\y -> (\k -> y (x k)))
\x -> (\y -> (\k -> y (x k)))
:: (t1 -> t2) -> (t2 -> t3) -> t1 -> t3
类型不应该是t1->(t2->(t3->t2))
吗?
答案 0 :(得分:3)
:t \x -> (\y -> x y) \x -> (\y -> x y) :: (t1 -> t2) -> t1 -> t2
这里的类型不应该是t1->(t2-> t1-> t2)?
不,t1->(t2->t1->t2)
与t1->t2->t1->t2
相同,t1
是三参数函数的类型(t2
,t1
和t2
类型)返回x
。但是,对于两个参数y
和typeOfX -> (typeofY -> typeOfResult)
\x -> (\y -> x y)
,只有两个lambdas。
正确的类型是
typeOfResult
(顺便说一下,上面没有括号。)
什么是x y
?是x
的类型,因此它是typeOfX
的返回类型,它必须是一个函数。
为了让代码键入check,我们必须让a -> b
是一个函数类型,比如typeOfResult = b
。在这种情况下,我们可以看到x y
。此外,在y
我们将x
传递给typeOfY = a
,这只能在typeOfX -> typeofY -> typeOfResult
=
(a -> b) -> a -> b
时进行检查。
所以,
t1
编译器使用了名称t2
和x
,但这是相同的类型。
圆括号在这里很重要,因为我们必须记住a -> b
是一个函数typeOfX -> typeofY -> typeOfK -> TypeOfResult
。
如上所述,如果没有括号,我们将得到一个三参数函数。
您可以尝试将相同的推理应用于第二个示例。从...开始
toppings
,慢慢发现这些类型实际上是什么。
答案 1 :(得分:0)
x
中的\x -> \y -> x y
类型为t1 -> t2
,这是第一个参数。
作为最外面的lambda,首先应用它,然后是y
您可以将其编写为\x y -> x y
,这只是自然顺序中的函数应用程序。