Я пытаюсь использовать пакет 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, вероятно, достаточно здесь, но, похоже, не существует.