Как я могу использовать предикат JSON `jsexpr? 'С Typed Racket?

Я пытаюсь использовать пакет json в Typed Racket, но у меня возникли проблемы с обработкой ввода предиката jsexpr?. Моя первая попытка состояла в том, чтобы просто использовать #:opaque.

(require/typed json
               [#:opaque JSExpr jsexpr?])

Проблема заключается в том, что jsexpr не является структурой, jsexpr? является просто предикатом, который проверяет, соответствует ли заданное значение определенной структуре. По правде говоря, тип jsexpr должен выглядеть примерно так.

(define-type JSExpr (U
                     'null Boolean String Integer Inexact-Real
                     (Listof JSExpr) (HashTable Symbol JSExpr)))

Итак, я бы просто использовал этот тип jsexpr, но все еще проблема. Теперь у меня есть тип (U JSExpr EOF), и мне нужно преобразовать его в тип jsexpr (я хочу исключить исключение, если получаю EOF). Поэтому я хочу сделать что-то вроде этого:

(cond
 [(jsexpr? json-data) json-data]
 [else (error "failed to parse JSON data")])

Это должно работать с набивкой Racket, но теперь у меня нет jsexpr?. К счастью, существует define-predicate, чтобы сгенерировать эту функцию для меня. К сожалению, он не работает с типом jsexpr, потому что предикат нуждается в плоском контракте, а потенциально изменяемые структуры данных, такие как HashTable, требуют заключенных контрактов.

Хорошо, ну как насчет ввода фактического предиката jsexpr? для типа вхождения для jsexpr?

(require/typed json
               [jsexpr? (-> Any Boolean : JSExpr)])

К сожалению, это также не работает, потому что фильтры не могут использоваться в require/typed.

Я понимаю, что реальная проблема, скорее всего, связана с тем, что HashTable изменчива, но это не то, что я могу изменить. Я полагаю, что я мог бы написать свою собственную функцию (-> Any Boolean : JSExpr), но это могло бы сорвать цель использования библиотеки.

Есть ли вообще способ сделать эту работу? Простой тип ImmutableHashTable, вероятно, достаточно здесь, но, похоже, не существует.

Ответ 1

Из списка рассылки:

Проблема заключается в том, что типизированный racket не знает, что значение типа String, например, будет иметь тип JSExpr или нет, поэтому вам придется поместить (assert x jsexpr?) вокруг всего, что вы хотите рассматривать как jsexpr.