Построить структуру с применением в типизированной ракетке

Я пытаюсь создать списки структур с применением в Typed Racket, но не могу понять, как заставить его работать. Я предполагаю, что это связано с проблемой полиморфных функций, но я не могу найти обходной путь.

Это работает:

(struct tt ([a : Integer]
            [b : Integer]))

(apply tt '(1 2))

Но это не (отредактировано):

(struct tt2 ([a : String]
             [b : (Vectorof Any)]))

(apply tt2 (list "A" (vector 1 2 2)))

С ошибкой:

 /usr/share/racket/collects/racket/private/kw.rkt:979:25: Type Checker: Bad
arguments to function in `apply':
Domain: String (Vectorof Any)
Arguments:  (List String (Vector Integer Integer Integer))

  in: (#%app apply tt23 (#%app list (quote "A") (#%app vector (quote 1) (quote 2) (quote 2))))

Есть ли какое-нибудь решение для этого?


person Matías Guzmán Naranjo    schedule 16.07.2018    source источник
comment
Дважды проверьте, какую программу вы используете. (apply tt2 '(1 (1 2 2))) отлично работает для меня. Это (apply tt2 '(1 '(1 2 2))) не работает из-за того, как работает quote. Я бы порекомендовал вам избегать использования quote для списков и вместо этого писать его как (apply tt2 (list 1 (list 1 2 2))).   -  person Alex Knauth    schedule 16.07.2018
comment
Если это связано с тем, что вы сделали распространенную ошибку, думая, что '(1 '(1 2 2)) совпадает с (list 1 (list 1 2 2)), см. В чем разница между цитатой и списком?.   -  person Alex Knauth    schedule 16.07.2018
comment
Я изменил пример, чтобы сделать его ближе к тому, что я на самом деле пытаюсь сделать, а именно к работе с векторами, которые могут быть разных типов. Я думаю, теперь это должно не работать?   -  person Matías Guzmán Naranjo    schedule 16.07.2018
comment
Хорошо. Векторы представляют собой изменяемую структуру данных, и возможность изменения делает проверку типов менее интуитивно понятной. (Vectorof Integer) нельзя использовать как (Vectorof Any), потому что (Vectorof Any) может быть изменено позже, чтобы включить нецелые числа. Решение состоит в том, чтобы при создании каждого вектора аннотировать его правильный тип. Это означает замену (vector ....) на (ann (vector ....) (Vectorof Any)), если вам нужно использовать его как (Vectorof Any).   -  person Alex Knauth    schedule 16.07.2018


Ответы (1)


Векторы представляют собой изменяемую структуру данных, и возможность изменения вектора делает проверку типов менее интуитивно понятной.

(Vectorof Integer) нельзя использовать как (Vectorof Any), потому что (Vectorof Any) может быть изменено позже, чтобы включить нецелые числа. Такая программа не проверяет тип

#lang typed/racket
(struct tt2 ([a : Integer]
             [b : (Vectorof Any)]))

(: v (Vectorof Integer)
(define v (vector 1 2 2))
(apply tt2 (list 1 v))

потому что если бы это было так, кто-то мог бы написать (vector-set! (tt2-b ....) 0 "not a number"), а затем v имел бы неправильный тип внутри себя.

Решение состоит в том, чтобы аннотировать каждый вектор к его правильному типу всякий раз, когда вы его создаете. Это означает выполнение одного из следующих действий:

  1. Замена (vector ....) на (ann (vector ....) (Vectorof Any)).
  2. Если вектор создается непосредственно как переменная v, замена (define v (vector ....)) на (define v : (Vectorof Any) (vector ....)).

Например:

#lang typed/racket
(struct tt2 ([a : Integer]
             [b : (Vectorof Any)]))

(apply tt2 (list 1 (ann (vector 1 2 2) (Vectorof Any))))

И имейте в виду, что это обычно необходимо для изменяемых вещей, таких как векторы, но не для неизменяемых вещей, таких как списки.

person Alex Knauth    schedule 16.07.2018