I have this data type, which should represent a table:
data R = R [Bool] deriving Eq -- Row
data T = T [R] deriving Eq -- Table
The problem is that it allows to have table of rows with different length, eg:
tab =T [R [True, False, True, True],
R [False, False, True, False],
R [False, False, False, True],
R [False, False]]
Is it possible to modify the data definition of T to impose that all the R elements have the same length?
You can do it with
DataKinds. This may be overcomplicated, though:I’d rather recommend @MathematicalOrchids alternative approach using smart constructors.
EDIT: What
DataKindsdo.The
DataKindsextension lets the compiler automatically create a new kind other than*for each data type one writes, and new types living in this kind from the constructors.So
Nat, besides being a simple ADT, also gives rise to a kindNat, and type constructorsZ :: NatandS :: Nat -> Nat. ThisSis comparable toMaybe :: * -> *— it just doesn’t use the kind of all types, but your new kindNat, inhabited only by the representations of the natural numbers.The point is, that now you also can define type constructors of mixed kinds. The classic example for this is
Vec:which has kind
Vec :: Nat -> * -> *. Similarly,Thas kindT :: Nat -> *. This let’s you use it with a type-encoded constant lenght, and leads to a type error if one two rows of different lenght are put together.Although this looks extremely powerful, it is in fact restricted. To get the everything out of such representations, dependently typed languages should like Agda should be used.