Я хотел бы создать тип, представляющий списки с конечным числом элементов.
Теперь наивный способ сделать это со строгой оценкой:
data FiniteList a
= Nil
| Cons a !(List a)
С этим бесконечным списки эквивалентны основанию.
Однако я хочу тип, который вообще запрещает создание таких списков. В идеале я хотел бы, чтобы любые попытки создать бесконечный список приводили к ошибке времени компиляции.
Я могу начать видеть, как это можно сделать, если я строю списки размеров с использованием GADTs
и 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
Если мы попытаемся создать что-то вроде
a = Cons 1 a
Мы получим ошибку типа, поскольку для этого требуется тип n ~ 'Succ n
.
Проблема в том, что это не один тип списка, а скорее класс типов, по одному для каждого размера списка. Так, например, если бы я хотел написать версию take
или drop
в этом списке, мне нужно было бы заняться серьезной зависимой типизацией.
Я хотел бы объединить все эти отдельные типы в единственный тип, который все еще обеспечивает конечность во время компиляции.
Можно ли это сделать?