Haskell 二级多态编译错误

2024-03-27

给出以下定义:

import Control.Monad.ST
import Data.STRef

fourty_two = do
  x <- newSTRef (42::Int)
  readSTRef x

在 GHC 下编译如下:

main = (print . runST) fourty_two -- (1)

但这并不:

main = (print . runST) $ fourty_two -- (2)

但随后作为bdonlan在评论中指出,这确实可以编译:

main = ((print . runST) $) fourty_two -- (3)

但是,这不能编译

main = (($) (print . runST)) fourty_two -- (4)

这似乎表明 (3) 仅由于中缀的特殊处理而编译$但是,它仍然没有解释为什么(1)能够编译。

问题:

1)我已阅读以下两个问题(first https://stackoverflow.com/questions/9468963/runst-and-function-composition, second https://stackoverflow.com/questions/8343239/type-error-with-rank-2-types-and-function-composition),我被引导相信$只能用单态类型实例化。但我同样会假设.只能用单态类型实例化,因此同样会失败。 为什么第一个代码成功但第二个代码不成功? (例如,GHC 对于第一种情况是否有特殊规则,但不能适用于第二种情况?)

2)当前是否有编译第二个代码的 GHC 扩展? (也许命令式多态性 http://www.haskell.org/ghc/docs/6.10.1/html/users_guide/other-type-extensions.html#impredicative-polymorphism在某个时候这样做过,但它似乎已被弃用,有什么可以替代它吗?)

3)有什么方法可以定义说`my_dollar`使用 GHC 扩展来做什么$确实如此,但也能够处理多态类型,所以(print . runST) `my_dollar` fourty_two编译?

编辑:建议答案:

另外,以下内容无法编译:

main = ((.) print runST) fourty_two -- (5)

这与 (1) 相同,只是不使用中缀版本..

因此,GHC 似乎对两者都有特殊规则$ and .,但仅限于它们的中缀版本。


  1. 我不确定我是否理解为什么第二个不起作用。我们可以看看类型print . runST并观察到它具有足够的多态性,因此责任不在于(.)。我怀疑 GHC 对于中缀有特殊规则($)只是还不够。如果您将此片段建议为他们的跟踪器上的错误,SPJ 和朋友可能会愿意重新检查它。

    至于为什么第三个例子有效,那只是因为((print . runST) $)具有足够的多态性;事实上,它等于print . runST.

  2. 什么都没有取代ImpredicativePolymorphism,因为 GHC 人员还没有看到任何用例,其中额外的程序员便利性超过了编译器错误的额外潜力。 (我认为他们也不会认为这是令人信服的,尽管我当然不是权威。)
  3. 我们可以定义一个稍微少一点的多态性($$):

    {-# LANGUAGE RankNTypes #-}
    infixl 0 $$
    ($$) :: ((forall s. f s a) -> b) -> ((forall s. f s a) -> b)
    f $$ x = f x
    

    然后你的示例类型检查可以使用这个新运算符:

    *Main> (print . runST) $$ fourty_two
    42
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 二级多态编译错误 的相关文章

随机推荐