#types #racket #pie-lang
Вопрос:
Я хочу понять и правильно использовать технику более конкретных типов, чтобы исключить нежелательные аргументы. Пример, приведенный около 6.37, представляет собой функцию first
, которая обертывает head
то, что нельзя вызвать для пустых векторов. Их решение состоит в том, чтобы смещать объявление типа с 1:
(claim first
(Pi ((E U) (l Nat))
(-> (Vec E (add1 l))
E)))
Это неудобно, потому что, если первые два параметра являются типом вектора и длиной, вы должны «лгать» при его вызове:
(first Atom 2 (vec:: 'A (vec:: 'B (vec:: 'C vecnil))))
ВОПРОС № 1: Я неправильно это осмысливаю? Необходимость «лгать», чтобы обойти что-то, кажется, что что-то на самом деле не понято.
first
Я сказал, что отправляю вектор длины атома 2, когда на самом деле он имеет длину 3. Чтобы назвать гипотетическим second
, потребуется нечестность на 2. Для third
, нечестность на 3 и так далее.
Я подумал, не лучше ли думать о l не как о длине вектора, а как о версии функции. Нет такой версии first
, которая принимала бы пустой вектор. Его нулевая версия принимает векторную длину 1. Его вторая версия имеет векторную длину 2:
первая версия | первый тип |
---|---|
0 | (-> (Vec E 1) E) |
1 | (-> (Vec E 2) E) |
… | … |
ВОПРОС № 2: Правильно ли так думать об этом? В книге используется l
, поэтому, похоже, они хотят, чтобы читатели думали «о длине».
Имея это в виду, я решил скорректировать first
, чтобы выбрать тип входного вектора и его длину. Старая реализация теперь first-worker
включена и дополнена новой first
:
(claim first-worker
(Pi ((T U) (version Nat))
(-> (Vec T (add1 version)) ; the i'th version takes vectors length i 1
T)))
(define first-worker
(lambda (E l)
(lambda (es)
(head es))))
(claim first
(Pi ((E U) (length Nat))
(-> (Vec E length) E)))
(define first
(lambda (E length input)
(first-worker E (sub1 length) input))) ; length vectors call version length-1
(first-worker Atom 3 (vec:: 'A (vec:: 'B (vec:: 'C vecnil))))
Но теперь нет защиты от первого с пустым вектором! Вызов типа (first Atom 0 vecnil)
все еще разрешен, если бы он выполнял проверку типа (это не так).
ВОПРОС № 3: Как я могу написать a first
, который принимает истинную длину входного вектора?
Любые другие советы и исправления приветствуются.