I would like to make a type that represents lists with a finite number of elements.
Now the naïve way to do this is with strict evaluation:
data FiniteList a
= Nil
| Cons a !(List a)
With this infinite lists are equivalent to bottom.
However I want a type which prevents the creation of such lists altogether. I would ideally like to have any attempts to build an infinite list cause a compile time error.
I can begin to see how this might be done if I build sized lists using GADTs and DataKinds.
data Natural = Zero | Succ Natural
data DependentList :: Natural -> Type -> Type where
Nil :: DependentList 'Zero a
Cons :: a -> DependentList n a -> DependentList ('Succ n) a
If we try and build something like
a = Cons 1 a
We get a type error since this requires a type n ~ 'Succ n.
The issue with this is that it is not a single list type but rather a class of types, one for each size of list. So for example if I wanted to write a version of take or drop on this list I would need to start getting into some serious dependent typing.
I would like to unify all of these separate types under a single type which still enforces finitude at compile time.
Can this be done?