I study the functions of the Haskell type family and compute the level level. It seems pretty easy to get level-level parametric polymorphism with PolyKinds :
{-
I can do things like :kind! Bool == Bool :kind! Bool == Bool or :kind! Int == Int :kind! Int == Int or :kind! Z == Z :kind! Z == Z and :kind! (IZ (SZ)) == (I (SZ) (S (SZ))) :kind! (IZ (SZ)) == (I (SZ) (S (SZ))) .
However, I want to make type + ad-hoc polymorphic. So this is limited to the cases that I give them. The 2 examples here are NatK view NatK and IntK view IntK .
At first I tried to make it parametrically polymorphic:
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)
It works, how can I do :kind! (I (SZ) Z) :+ (I (SZ) Z) :kind! (I (SZ) Z) :+ (I (SZ) Z) .
However, I can also do :kind! Bool :+ Bool :kind! Bool :+ Bool . And this makes no sense, but allows you to use it as a simple type constructor. I want to create a type family that does not allow such erroneous types.
At that moment I was lost. I tried class types with the type parameter. But that did not work.
class NumK (a :: k) (b :: k) where type Add ab :: 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 ab) 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)
It still allows :kind! Add Bool Bool :kind! Add Bool Bool .
Is this ConstraintKinds extension, where do I need to limit :+ or Add some “cool class”?
source share