繁体   English   中英

当将typeclass函数包装在存在中时,类型变量不明确

[英]Ambiguous type variable when wrapping typeclass function in existential

我在解释器中使用类型化的无标签最终编码。 不幸的是,我在类型检查阶段遇到了问题。 最小测试用例如下:

{-# LANGUAGE RankNTypes, ExistentialQuantification, NoMonomorphismRestriction #-}
class Program repr where
    ...
    intro1 :: repr a (a, ())
    ...

data DynTerm repr = forall x y. (Typeable x, Typeable y) => DynTerm (repr x y)

ghci> DynTerm intro1

这将产生以下错误:

Could not deduce (Typeable x0) arising from a use of `DynTerm'
from the context (Program repr)
  bound by the inferred type of it :: Program repr => DynTerm repr
  at <interactive>:3:1-14
The type variable `x0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
  instance Typeable Void -- Defined in `Data.Void'
  instance [overlap ok] Typeable ()
    -- Defined in `Data.Typeable.Internal'
  instance [overlap ok] Typeable Bool
    -- Defined in `Data.Typeable.Internal'
  ...plus 25 others
In the expression: DynTerm intro1
In an equation for `it': it = DynTerm intro1

我希望编译器的理由如下:

  • 尝试将a与x统一。
  • 将Typeable a添加到约束列表中(我可以通过类型注释手动添加它,这没有什么区别)。
  • 成功。
  • 尝试将y与(a,())统一。
  • 请注意,由于我们假设Typeable a,因此Typeable(a,())也成立。
  • 成功。

但是,似乎无法统一x。

使用DynTerm构造函数构造DynTerm类型的值时,GHC必须知道具体的类型xy才能确定应将哪些Typeable字典打包。在测试表达式中,您没有提供足够的类型信息来确定具体类型,因此您会收到某些类型变量不明确的错误。 如果您专门选择一个具体的Typeable类型,则可以使用它。

示例(带有ScopedTypeVariables ):

test :: forall repr. Program repr => DynTerm repr
test = DynTerm (intro1 :: repr Int (Int, ()))

正如kosmikus所指出的, ExistentialQuantification意味着您将对类型变量进行抽象,但是数据类型的实现者必须选择一个单态类型:

构造此类型的值时,s将实例化为某种具体类型。 分析这样的值时,s是抽象的。

考虑以下:

data D = forall a . Show a => D (a -> String) 
-- test0 = D show -- Invalid!
test1 = D (show :: () -> String)

data E = E (forall a . Show a => a -> String)
test2 = E show -- Invalid!
-- test3 = E (show :: () -> String)

所以也许你想要

data DynTerm repr = DynTerm (forall x y. (Typeable x, Typeable y) => repr x y)

但这对intro1仍然intro1 -它不是足够多态的( (a,())x更具体)。 如果您有intro2 :: Program repr => repr xy ,则可以编写DynTerm intro2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM