我有一个表达式:
gcastWith p1 $
gcastWith p2 $
e
这没关系。现在我试图将其重写为:
((gcastWith p1) .
(gcastWith p2)) $
e
它不起作用(没有进行类型检查)。然而,这有效:
((gcastWith p1) .
(gcastWith p2)) -- note I removed the dollar
e
我是否遗漏了有关$
和.
如何运作的明显内容?
答案 0 :(得分:7)
我猜它是由类型推断如何工作引起的一些限制。在基本的Hindley-Milner类型中,如
f :: (forall a. G a) -> T
是被禁止的。 GHC Haskell允许它们(启用了合适的扩展),但仍然使用HM限制,要求类型变量永远不能实例化为多类型。
这会导致一些意外:f e
类型检查,但f $ e
失败,因为$
类型的类型变量应该实例化为多元类型。
e :: forall a. G a
f :: (forall a. G a) -> T
f e :: T
($) :: (b -> c) -> b -> c
Type checking ($) f e:
b ~ (forall a. G a) -- forbidden polytype!
c ~ T
由于f $ e
在Haskell中非常非常,并且我们真的希望runST $ do ....
之类的东西能够正常工作,所以GHC开发人员为{{{{}}添加了一个特殊情况的输入规则1}}。基本上,完全应用后,$
的输入类似于f $ e
。
目前f e
的打字系统中没有这种特殊情况。这可能会在f . g . h $ e
正常工作时失败。