Haskell($)是一个神奇的算子?

Yel*_*ika 54 haskell

说我有以下功能:

infixr 0 <|

{-# INLINE (<|) #-}
(<|) :: (a -> b) -> a -> b
f <| x = f x

foo :: a -> (forall b. b -> b) -> a
foo x f = f x
Run Code Online (Sandbox Code Playgroud)

以下不进行类型检查:

ghci> foo 3 <| id

Couldn't match expected type `forall b. b -> b'
            with actual type `a0 -> a0'
In the second argument of `(<|)', namely `id'
In the expression: f 3 <| id
In an equation for `it': it = f 3 <| id
Run Code Online (Sandbox Code Playgroud)

但是,foo 3 $ id 确实如此.

(<|)的定义(据我所知)与($)的定义相同.我几乎从基础库源中删除了定义,并将($)的每个实例都更改为(<|).编译魔术?

J. *_*son 69

是的,有一小部分编译器魔法($)来处理impredicative类型.引入它是因为每个人都期望

runST $ do
  foo
  bar
  baz
Run Code Online (Sandbox Code Playgroud)

对于typecheck,但它不能正常.有关详细信息,请参阅此处(搜索runST),此电子邮件和此电子邮件.缺点是在类型检查器中实际上有一个特殊的规则,($)它使得它能够解决impredicative类型的常见情况.

  • 另外,与答案本身无关,*很好找*.很难注意到这个特殊的编译器魔法. (22认同)
  • 这是Simon PJ谈论impredicativity检查和($)快捷方式的电子邮件http://www.haskell.org/pipermail/glasgow-haskell-users/2010-November/019431.html (6认同)
  • trac页面只是说GHC做了从左到右的实例化,而不是特殊情况`($)`.它实际上只用于`($)`吗? (5认同)