以下编译没有 PolyKinds
:
{-# LANGUAGE TypeFamilies, GADTs #-}
type family Modulus zq
type family Foo zq q
data Bar :: (* -> *) where
Bar :: (zq' ~ Foo zq (Modulus zq)) => Bar (zq -> zq')
的所有外观都是代表模算术 modzq
的某种类型(种类) 。用它来表示这些模数会很方便。如果我在类型族中添加和多类模量:*
q
Nats
PolyKinds
{-# LANGUAGE TypeFamilies, GADTs, PolyKinds #-}
type family Modulus zq :: k
type family Foo zq (q :: k)
data Bar :: (* -> *) where
Bar :: (zq' ~ Foo zq (Modulus zq)) => Bar (zq -> zq')
GHC 7.8 抱怨:
Could not deduce (zq' ~ Foo zq (Modulus zq))
...
In the ambiguity check for:
forall zq' zq. zq' ~ Foo zq (Modulus zq) => Bar (zq -> zq')
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the definition of data constructor ‘Bar’
添加PolyKinds
真的使这个模棱两可吗?歧义在哪里?还相关:-XAllowAmbiguousTypes 何时合适?
如果我向 GHC 扔骨头并将AllowAmbiguousTypes
错误从 GADT 的声明移动到 GADT 的使用(没有添加扩展的建议):
bar :: (zq' ~ Foo zq (Modulus zq))
=> Bar (zq -> zq')
bar = Bar
这让我觉得使用AllowAmbiguousTypes
的是 GHC 红鲱鱼。
编辑
为了澄清,上面的类型可能被实例化如下:
newtype Zq q = Zq Int
然后zq ~ (Zq 3)
, q ~ 3
, 和Modulus (Zq 3) ~ 3
, Foo (Zq 3) 3 ~ (Zq 3)
(我将工作从类型家族中剥离出来Foo
,所以将其视为身份。)