GHC 无法推断未举升类型的种类。

5

我遇到了Happy生成的似乎是无效代码的问题,这个问题可以归结为GHC不能为函数推断出一个多态类型签名。以下是一个示例:

{-# Language MagicHash #-}

f x = ()

main = pure (f 1#)

由于 GHC 推断出 f :: a -> (),其中 a :: *,因此此操作失败。

Couldn't match a lifted type with an unlifted type
   When matching the kind ofGHC.Prim.Int#’
 • In the first argument of ‘f’, namely ‘1#’
   In the first argument of ‘pure’, namely ‘(f 1#)’
   In the expression: pure (f 1#)

有没有一些语言操作符可以让我轻松编译这段代码?我知道理论上我可以添加类型签名,但这是由Happy生成的代码,我不想手动修改任何内容。


1
这似乎很相关:https://dev59.com/U1sW5IYBdhLWcg3wKkgz#35320729。基本上,一个函数不能在种类上具有多态性,除非你真的想要,并且只能在GHC 8+中实现。 - Fyodor Soikin
3
如果Happy生成的代码以这种方式无法编译,则可能是Happy中的一个错误(也许可以解决!)。您能否组合一个最小的Happy示例来产生这样的代码?我认为GHC从未推断出除多态类型' * '以外的任何其他类型。 - user2407038
1
@user2407038 虽然我的问题仍然存在,但这个特定的 Happy bug 很容易修复。基本上,任何使用 happyMonad2Reduce 生成的代码,如果没有使用 -a 选项生成,则会出现 nt :: Int# 变量的问题(因为它在没有 -a 的情况下不被使用,所以会出现类型推断问题)。我目前正在解决一些更严重的 Happy 问题,所以将 问题提交给问题列表放在了后面。 :) - Alec
1
@Alec 感谢解释,我看到你已经意识到工具链中更高层次的问题/解决方案。这个问题在比 Happy 更广泛的上下文中很有趣,但不幸的是我认为它没有解决方法(除了编写类型签名)。祝好运! - user2407038
3
结论是,无论如何,参数传递给f函数的类型都不能是多种类型(具体来说,是levity-polymorphic类型)。变量x的类型属于levity-polymorphic类型,而且没有任何变量可以拥有这样的类型。因此,你需要GHC推断出单态化类型。我的猜测是,尽管类型检查器可以将类多态代码延迟应用到单态化限制上,但它没有机制来对基本的levity-polymorphic代码这样做。 - dfeuer
1个回答

2
@dfeuer 暗示过,这是不可能的。在最坏的情况下,GHC必须查找整个项目中给定函数的用法,以推断参数的轻重性。
这被报告为Happy中的一个错误,并已修复。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接