Haskell评级为两个多态性编译错误

编程入门 行业动态 更新时间:2024-10-28 06:33:51
本文介绍了Haskell评级为两个多态性编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 给定以下定义:

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)我已阅读以下两个问题(第一个问题:第一个问题,第二个)和我我们相信 $ 只能用单形类型实例化。但我会同样假设。只能用单形类型实例化,结果也会失败。 为什么第一个代码成功,但第二个代码不成功? (例如,GHC对第一种情况有特殊规则,它不能在第二种情况下适用)? 2)是否有当前的GHC扩展编译第二个代码? (也许 ImpredicativePolymorphism 在某些时候做了这个,但它似乎不赞成,有什么取代它?)

3)有没有什么办法来定义说 `my_dollar` 使用GHC扩展来完成 $ 的操作,但也可以处理多态类型,所以(print 。runST)`my_dollar` fourty_two 编译?

编辑:建议的答案:

b

另外,以下编译失败:

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

这与(1)相同,除非不使用中缀版本。。

因此,GHC似乎对 $ 和。,但只有它们的中缀版本。 解决方案

  • 我不确定我明白为什么第二个不起作用。我们可以看看 print的类型。 runST 并观察它是足够多态的,所以不应该指责(。)。我怀疑GHC对中缀($)的特殊规则不够充分。 SPJ和朋友可能会开放,重新检查它,如果你提出这个片段作为他们的跟踪器的错误。

    至于第三个例子的工作原理,那就是因为再次,((print。runST)$)的类型足够多态;实际上,它等于 print的类型。 runST 。

  • 没有任何内容替代 ImpredicativePolymorphism ,因为GHC人没有看到任何额外的程序员便利超出了编译器错误的额外潜力的用例。 (我不认为他们会将这看作是引人注目的,虽然我当然不是权威。)
  • 我们可以定义一个稍微少一点的多态< { - #LANGUAGE RankNTypes# - } infixl 0 $$ ($$)::((forall s。fsa) - > b) - > ((forall s。fsa) - > b)f $$ x = fx

    然后你的例子使用这个新的操作符进行类型检查:

    * Main> (print。runST)$$ fourty_two 42

  • Given the following definitions:

    import Control.Monad.ST import Data.STRef fourty_two = do x <- newSTRef (42::Int) readSTRef x

    The following compiles under GHC:

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

    But this does not:

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

    But then as bdonlan points out in a comment, this does compile:

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

    But, this does not compile

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

    Which seems to indicate that (3) only compiles due to special treatment of infix $, however, it still doesn't explain why (1) does compile.

    Questions:

    1) I've read the following two questions (first, second), and I've been led to believe $ can only be instantiated with monomorphic types. But I would similarly assume . can only be instantiated with monomorphic types, and as a result would similarly fail. Why does the first code succeed but the second code does not? (e.g. is there a special rule GHC has for the first case that it can't apply in the second?)

    2) Is there a current GHC extension that compiles the second code? (perhaps ImpredicativePolymorphism did this at some point, but it seems deprecated, has anything replaced it?)

    3) Is there any way to define say `my_dollar` using GHC extensions to do what $ does, but is also able to handle polymorphic types, so (print . runST) `my_dollar` fourty_two compiles?

    Edit: Proposed Answer:

    Also, the following fails to compile:

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

    This is the same as (1), except not using the infix version of ..

    As a result, it seems GHC has special rules for both $ and ., but only their infix versions.

    解决方案

  • I'm not sure I understand why the second doesn't work. We can look at the type of print . runST and observe that it is sufficiently polymorphic, so the blame doesn't lie with (.). I suspect that the special rule that GHC has for infix ($) just isn't quite sufficient. SPJ and friends might be open to re-examining it if you propose this fragment as a bug on their tracker.

    As for why the third example works, well, that's just because again the type of ((print . runST) $) is sufficiently polymorphic; in fact, it's equal to the type of print . runST.

  • Nothing has replaced ImpredicativePolymorphism, because the GHC folks haven't seen any use cases where the extra programmer convenience outweighed the extra potential for compiler bugs. (I don't think they'd see this as compelling, either, though of course I'm not the authority.)
  • We can define a slightly less polymorphic ($$):

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

    Then your example typechecks okay with this new operator:

    *Main> (print . runST) $$ fourty_two 42

  • 更多推荐

    Haskell评级为两个多态性编译错误

    本文发布于:2023-11-04 10:04:01,感谢您对本站的认可!
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:多态性   错误   两个   Haskell

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!