我正在研究 Haskell 的类型族特性和类型级计算。使用以下方法在类型级别获得参数多态性似乎很容易PolyKinds
:
{-# LANGUAGE DataKinds, TypeFamilies, KindSignatures, GADTs, TypeOperators, UndecidableInstances, PolyKinds, MultiParamTypeClasses, FlexibleInstances #-}
data NatK = Z | S NatK
data IntK = I NatK NatK
infix 6 +
type family (x :: NatK) + (y :: NatK) :: NatK where
Z + y = y
(S x) + y = S (x + y)
-- here's a parametrically polymorphic (==) at the type-level
-- it also deals specifically with the I type of kind IntK
infix 4 ==
type family (a :: k) == (b :: k) :: Bool where
(I a1 a2) == (I b1 b2) = (a1 + b2) == (a2 + b1)
a == a = True
a == b = False
我可以做类似:kind! Bool == Bool
or:kind! Int == Int
或:kind! Z == Z
and的事情:kind! (I Z (S Z)) == (I (S Z) (S (S Z)))
。
但是我想使type +
临时多态。所以它仅限于我给它的实例。这里的 2 个实例是 kindNatK
类型和 kind 类型IntK
。
我首先尝试使其参数化多态:
infix 6 :+
type family (x :: k) :+ (y :: k) :: k where
Z :+ y = y
(S x) :+ y = S (x :+ y)
(I x1 x2) :+ (I y1 y2) = I (x1 :+ y1) (x2 :+ y2)
这行得通,我可以做到:kind! (I (S Z) Z) :+ (I (S Z) Z)
。
不过我也可以:kind! Bool :+ Bool
。这没有任何意义,但它允许它作为一个简单的类型构造函数。我想创建一个不允许此类错误类型的类型系列。
在这一点上,我迷路了。type
我尝试了带参数的类型类。但这没有用。
class NumK (a :: k) (b :: k) where
type Add a b :: k
instance NumK (Z :: NatK) (b :: NatK) where
type Add Z b = b
instance NumK (S a :: NatK) (b :: NatK) where
type Add (S a) b = S (Add a b)
instance NumK (I a1 a2 :: IntK) (I b1 b2 :: IntK) where
type Add (I a1 a2) (I b1 b2) = I (Add a1 b1) (Add a2 b2)
它仍然允许:kind! Add Bool Bool
.
这是否与ConstraintKinds
扩展有关,我需要将:+
or限制Add
为某种“类”?