[英]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
我希望编译器的理由如下:
但是,似乎无法统一x。
使用DynTerm
构造函数构造DynTerm
类型的值时,GHC必须知道具体的类型x
和y
才能确定应将哪些Typeable
字典打包。在测试表达式中,您没有提供足够的类型信息来确定具体类型,因此您会收到某些类型变量不明确的错误。 如果您专门选择一个具体的Typeable
类型,则可以使用它。
示例(带有ScopedTypeVariables
):
test :: forall repr. Program repr => DynTerm repr
test = DynTerm (intro1 :: repr Int (Int, ()))
正如kosmikus所指出的, ExistentialQuantification
意味着您将对类型变量进行抽象,但是数据类型的实现者必须选择一个单态类型:
考虑以下:
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.