我在解释器中使用了类型化的无标记最终编码。不幸的是,我遇到了类型检查阶段的问题。最小的测试用例如下:
{-# 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。
答案 0 :(得分:3)
使用DynTerm
构造函数构造DynTerm
类型的值时,GHC必须知道具体类型x
和y
才能确定Typeable
应该打包字典。在测试表达式中,您没有提供足够的类型信息来确定具体类型,因此您会收到某些类型变量不明确的错误。如果您专门选择具体的Typeable
类型,它就可以使用。
示例(带ScopedTypeVariables
):
test :: forall repr. Program repr => DynTerm repr
test = DynTerm (intro1 :: repr Int (Int, ()))
答案 1 :(得分:2)
正如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
- 它的多态性不够((a,())
比x
更具体)。如果您有intro2 :: Program repr => repr x y
,则可以撰写DynTerm intro2
。