这有点深奥,但令人抓狂。在对another question的回答中,我注意到在这个完全有效的程序中
poo :: String -> a -> a
poo _ = id
qoo :: (a -> a) -> String
qoo _ = ""
roo :: String -> String
roo = qoo . poo
在检查a
的过程中,类型变量roo
既未得到解决也未被推广。我想知道在GHC的核心语言翻译中会发生什么,这是教会风格的System F变体。让我用简明的类型lambdas /\
和类型的应用程序@
来拼写出来的东西。
poo :: forall a. [Char] -> a -> a
poo = /\ a -> \ s x -> id @ a
qoo :: forall a. (a -> a) -> [Char]
qoo = /\ a -> \ f -> [] @ Char
roo :: [Char] -> [Char]
roo = (.) @ [Char] @ (? -> ?) @ [Char] (qoo @ ?) (poo @ ?)
?
地方究竟发生了什么? roo
如何成为有效的核心术语?或者我们真的得到一个神秘的空洞量词,尽管类型签名是什么?
roo :: forall a. [Char] -> [Char]
roo = /\ a -> ...
我刚检查了那个
roo :: forall . String -> String
roo = qoo . poo
通过确定,这可能会或可能不会意味着没有额外量化的东西。
那里发生了什么?
答案 0 :(得分:17)
这是GHC生成的核心(在添加一些NOINLINE
pragma之后)。
qoo_rbu :: forall a_abz. (a_abz -> a_abz) -> GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs]
qoo_rbu = \ (@ a_abN) _ -> GHC.Types.[] @ GHC.Types.Char
poo_rbs :: forall a_abA. GHC.Base.String -> a_abA -> a_abA
[GblId, Arity=1]
poo_rbs = \ (@ a_abP) _ -> GHC.Base.id @ a_abP
roo_rbw :: GHC.Base.String -> GHC.Base.String
[GblId]
roo_rbw =
GHC.Base..
@ (GHC.Prim.Any -> GHC.Prim.Any)
@ GHC.Base.String
@ GHC.Base.String
(qoo_rbu @ GHC.Prim.Any)
(poo_rbs @ GHC.Prim.Any)
似乎GHC.Prim.Any
用于多态类型。
来自the docs(强调我的):
类型构造函数
Any
是您可以不安全地强制任何类型的类型 举起型,然后回来。
- 它被抬起,因此用指针
表示- 它没有声称 是一种数据类型,这对代码生成器很重要,因为 代码gen可以输入数据值,但从不输入函数值。
它也用于在类型后实例化非约束类型变量 检查。强>
将这样的类型替换为非约束类型是有意义的,否则像length []
这样的琐碎表达式会导致模糊的类型错误。
答案 1 :(得分:0)
这不是问题。在 roo 的签名中,类型变量a不会按原样显示。一个更简单的例子是表达式
const 1 id
,其中
id :: forall a.a->a