Aggiornamento FParsec: upgrade sindacati discriminati per soddisfare le nuove parità / vincoli di confronto
-
21-09-2019 - |
Domanda
Quindi, da un hi lar serie di eventi pagherò , ho scaricato la fonte FParsec e ha cercato di costruirlo. Purtroppo, non è compatibile con il nuovo 1.9.9.9. Ho sistemato i problemi facili, ma ci sono un paio di sindacati discriminati che ancora non funzionano.
In particolare, post di Don Syme spiega che i sindacati discriminati contenenti elementi di tipo obj
o ->
non ottengono automaticamente vincoli di uguaglianza o di confronto, dal momento che gli oggetti non supportano il confronto e le funzioni non supportano l'uguaglianza sia . (Non è chiaro se l'uguaglianza generato automaticamente / confronto è stato buggy prima, ma il codice non sarà nemmeno la compilazione ora che non sono più generati.)
Ecco alcuni esempi di tossicodipendenti problematici:
type PrecedenceParserOp<'a,'u'> =
| PrefixOp of string * Parser<unit,'u> * int * bool * ('a -> 'a)
| others ...
type ErrorMessage =
| ...
| OtherError of obj
| ...
Ecco l'incriminato utilizza:
member t.RemoveOperator (op: PrecedenceParserOp<'a, 'u>) =
// some code ...
if top.OriginalOp <> op then false // requires equality constraint
// etc etc ...
o, per il vincolo di confronto
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 ...
Per quanto posso dire, la soluzione di Don di codifica ogni istanza con un int unico è il modo giusto per implementare un vincolo di uguaglianza custom / confronto (o forse un int tupla univoco in modo che i rami individuali del DU possono essere ordinati) . Ma questo è scomodo per l'utente del DU. Ora, la costruzione del DU richiede chiamare una funzione per ottenere il prossimo francobollo.
C'è qualche modo per nascondere la tag-ottenere e presentare gli stessi costruttori per gli utenti della biblioteca? Cioè, per cambiare l'implementazione senza cambiare l'interfaccia? Questo è particolarmente importante perché sembra (da quello che ho capito del codice) che PrecedenceParserOp
è un tipo di pubblico.
Soluzione
Cosa fonte hai scaricare FParsec? Ho afferrato le ultime dal FParsec BitBucket repository , e non ho dovuto apportare modifiche al tutto alla fonte FParsec per farlo compilare in VS 2010 RC.
Edit: mi correggo. Ho avuto errori di generazione dei progetti di esempio InterpLexYacc e InterpFParsec, ma i progetti di base FParsec e FParsecCS costruire bene.
Altri suggerimenti
Una cosa che potreste fare è aggiungere attributi [<CustomEquality>]
e [<CustomComparison>]
e definire una propria implementazione .Equals
override e IComparable
. Naturalmente, ciò richiederebbe di gestire i componenti obj
e _ -> _
se stessi in un modo appropriato, che può o non può essere possibile. Se è possibile controllare ciò che viene passato al costruttore OtherError
, si dovrebbe essere in grado di fare questo lavoro per la ErrorMessage
dal downcasting il obj
a un tipo che è essa stessa strutturalmente comparabile. Tuttavia, il caso PrecendenceParserOp
è un po 'più complicato -. Potrebbe essere in grado di cavarsela con l'utilizzo di uguaglianza di riferimento sui componenti di funzione finché non hai bisogno di confronto e