Ответ 1
SomeNat
определяется по существу:
data SomeNat = forall n. KnownNat n => SomeNat (Proxy n)
который читается как SomeNat
, содержит, ну, "some n :: Nat
". Proxy
- это одноэлементный режим, который позволяет поднять этот уровень n
до уровня уровня, чтобы удовлетворить типу системы. На зависимом языке мы нуждаемся в такой конструкции очень редко. Мы можем определить SomeNat
более явным образом с помощью GADTs
:
data SomeNat where
SomeNat :: forall n. KnownNat n => Proxy n -> SomeNat
So SomeNat
содержит a Nat
, который не известен статически.
Тогда
someNatVal :: Integer -> Maybe SomeNat
читается как "someNatVal
получает Integer
и Maybe
возвращает hiden Nat
". Мы не можем вернуть KnownNat
, потому что Known
означает "известно на уровне уровня", но мы ничего не знаем о произвольном Integer
на уровне типа.
Обратная (по модулю SomeNat
оболочка и Proxy
вместо Proxy
) someNatVal
равна
natVal :: forall n proxy. KnownNat n => proxy n -> Integer
Считывается как "natVal
получает то, что имеет Nat
в своем типе, и возвращает Nat
, преобразованный в Integer
".
Экстрастенциально квантифицированные типы данных обычно используются для переноса значений времени выполнения. Предположим, вы хотите прочитать Vec
(список со статически известной длиной) из STDIN
, но как бы вы статически вычисляли длину ввода? Выхода нет. Таким образом, вы завершаете список, который вы прочитали, в соответствующем экзистенциально квантифицированном типе данных, таким образом: "Я не знаю длины, но существует один".
Однако во многих случаях это слишком много. Чтобы сделать что-то с экзистенциально квантованным типом данных, вам необходимо быть общим: например. если вам нужно найти сумму элементов SomeVec
, вы должны определить sumVec
для Vec
с произвольной длиной. Затем разверните SomeVec
и примените sumVec
, сказав: "Я не знаю длины обернутого Vec
, но sumVec
не заботится". Но вместо этого wrapping-unwrapping вы можете напрямую использовать CPS.
Однако из-за этой общности вам нужно включить ImpredicativeTypes
, чтобы иметь возможность определять, скажем, список с такими продолжениями. В этом случае список с экзистенциально квантифицированными данными является общим шаблоном, который позволяет обойти ImpredicativeTypes
.
Что касается вашего примера, с правильно определенными Nat
s, версия, которая сравнивает Nat
, lazier, чем версия, которая сравнивает Integer
s.