以下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 。
我们可以定义一个稍微少一点的多态< 然后你的例子使用这个新的操作符进行类型检查: { - #LANGUAGE RankNTypes# - } infixl 0 $$ ($$)::((forall s。fsa) - > b) - > ((forall s。fsa) - > b)f $$ x = fx
Given the following definitions:
import Control.Monad.ST import Data.STRef fourty_two = do x <- newSTRef (42::Int) readSTRef xThe 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.
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 xThen your example typechecks okay with this new operator:
*Main> (print . runST) $$ fourty_two 42
更多推荐
Haskell评级为两个多态性编译错误
发布评论