在我最近的一个问题中,我发现了一个使用种类类型类型的answer。请注意,在HasNProxyK k
中,k
是第二个NProxyK
参数的类型。
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeInType #-}
import GHC.TypeLits hiding ( (*) )
import Data.Kind
class HasNProxyK j where
data NProxyK (n :: Nat) (a::j) :: k
instance HasNProxyK Type where
data NProxyK n a = NProxyK0
instance HasNProxyK k => HasNProxyK (j -> k) where
data NProxyK n f = NProxyKSuc -- or NProxyKS (ProxyK n (f a))
type family ToNProxyK (n :: Nat) (a :: k) :: k where
ToNProxyK n (a :: Type) = NProxyK n a
ToNProxyK n (a :: j -> k) = NProxyK n a
我至少以一种方式对上述内容不满意。我想用constraint in its kind声明类型族,例如:
type family ToNProxyK (n :: Nat) (a :: HasNProxyK k => k) :: k where
ToNProxyK n (a::Type) = Type
ToNProxyK n (a :: j -> k) = NProxyK n a
我的目的是限制a
属于HasNProxyK
的种类。而且,为了使用类型族,我必须知道该类实例已满足-希望在编译时捕获诸如ToNProxyK 3 True
之类的声明。但是,当我尝试上面的ghc告诉我:
src/Traversal.hs:359:15: error:
• Expected kind ‘HasNProxyK k0 => k0’,
but ‘(a :: Type)’ has kind ‘*’
• In the second argument of ‘ToNProxyK’, namely ‘(a :: Type)’
In the type family declaration for ‘ToNProxyK’
|
359 | ToNProxyK n (a :: Type) = NProxyK n a
| ^^^^^^^^^^^
我从中得到的是,我实际上并没有在声明我认为在声明的内容。我指定了一种新的种类,而不仅限于
被接受。我也尝试过在成员类型(HasNProxyK Type => Type
)中加入约束,但这只会导致其他问题。
那么,我在这个被束缚的善良家庭中实际上在说什么?是否有一种方法可以限制此类型族中的k
禁止使用诸如ToNProxyK n True
之类的类型?
答案 0 :(得分:2)
据我所知,我找不到理想的方法来实现受限的封闭类型族。
但是,对于您的特定情况,使用在类型类中声明的类型族可能就足够了,它可以根据需要约束k
。
class HasNProxyK k => C k (n :: Nat) (a :: k) where
type ToNProxyK k n a :: k
instance C Type n a where
type ToNProxyK Type n a = NProxyK n a
instance HasNProxyK k => C (j -> k) n a where
type ToNProxyK (j -> k) n a = NProxyK n a
这样做,我们将失去对 closed 类型族的“自顶向下”处理。就您而言,Type
和j -> k
之间没有重叠,因此这不成问题。
简单的变体:
class HasNProxyK k => C k where
type ToNProxyK k (n :: Nat) (a :: k) :: k
instance C Type where
type ToNProxyK Type n a = NProxyK n a
instance HasNProxyK k => C (j -> k) where
type ToNProxyK (j -> k) n a = NProxyK n a