Итак, по серии hi lar ious я скачал исходный код FParsec и попытался его построить. К сожалению, он не совместим с новым 1.9.9.9. Я исправил простые проблемы, но есть пара союзов, которые все еще не работают.
В частности, Пост Дона Сайма объясняет, что различимые союзы, содержащие элементы типа obj
или ->
, не получают автоматически равенство или ограничения сравнения, поскольку объекты не поддерживают сравнение, а функции don ' не поддерживает равенство либо. (Непонятно, была ли ошибка в сгенерированном автоматически равенстве / сравнении раньше, но код даже не скомпилируется, поскольку они больше не генерируются.)
Вот несколько примеров проблемных DU:
type PrecedenceParserOp<'a,'u'> =
| PrefixOp of string * Parser<unit,'u> * int * bool * ('a -> 'a)
| others ...
type ErrorMessage =
| ...
| OtherError of obj
| ...
Вот оскорбительное использование:
member t.RemoveOperator (op: PrecedenceParserOp<'a, 'u>) =
// some code ...
if top.OriginalOp <> op then false // requires equality constraint
// etc etc ...
или, для ограничения сравнения
let rec printMessages (pos: Pos) (msgs: ErrorMessage list) ind =
// other code ...
for msg in Set.ofList msgs do // iterate over ordered unique messages
// etc etc ...
Насколько я могу судить, решение Дона пометить каждый экземпляр уникальным int - это правильный путь для реализации пользовательского ограничения равенства / сравнения (или, возможно, уникального кортежа, позволяющего упорядочить отдельные ветви DU). , Но это неудобно для пользователя DU. Теперь построение DU требует вызова функции для получения следующего штампа.
Есть ли способ скрыть получение тегов и представить одинаковые конструкторы пользователям библиотеки? То есть изменить реализацию без изменения интерфейса? Это особенно важно, поскольку кажется (из того, что я понимаю в коде), что PrecedenceParserOp
является публичным типом.