2014-07-02 12 views
5

Spesso ho bisogno di fare confronti con i valori Data.Text con diversi requisiti per la distinzione tra maiuscole e minuscole - questo compare spesso quando sto usando chatter per le attività di NLP.confronti maiuscole/insensibili per Data.Text?

Ad esempio, durante la ricerca di token per le attività di estrazione delle informazioni, ho spesso bisogno di cercare in base alle relazioni di uguaglianza che sono meno restrittive rispetto all'equità delle stringhe standard. La maiuscole e minuscole è la più comune di queste modifiche, ma spesso è una funzione del token specifico. Un termine come "attivare" potrebbe essere in genere minuscolo, ma se è la prima parola in una frase, inizierà con una maiuscola iniziale, o se usato in un titolo può essere in maiuscolo o in minuscolo in maiuscolo, quindi i confronti che ignorano il caso hanno senso. Viceversa, un acronimo (ad esempio "US") ha una semantica diversa a seconda della capitalizzazione.

Questo è tutto ciò che posso dire che non posso creare facilmente un wrapper typeclass per ogni classe di uguaglianza, poiché è un aspetto basato sul valore. (quindi il pacchetto case-insensitive non sembra funzionare).

Finora, sto usando toLower di fare una rappresentazione canonica, e confrontando quelle rappresentazioni in modo da poter creare versioni personalizzate di funzioni di confronto di testo che prendono una bandiera sensibilità, ad esempio:

matches :: CaseSensitive -> Text -> Text -> Bool 
matches Sensitive x y = x == y 
matches Insensitive x y = (T.toLower x) == (T.toLower y) 

Tuttavia, Sono preoccupato che ciò richieda passaggi extra sul testo di input. Potrei immaginare che si fonda in alcuni casi, ma probabilmente non tutti (ad esempio: T.isSuffixOf, T.isInfixOf).

C'è un modo migliore per farlo?

+5

Si dovrebbe davvero usare 'toCaseFold' invece di' toLower' per confronti senza distinzione tra maiuscole e minuscole. Forse non importa così tanto quando sai per certo che tutto il testo sarà inglese, ma è comunque buona norma usare l'approccio più generale. – Carl

+0

Probabilmente potresti usare una funzione di primo livello 'isCaseSensitive', magari usando un' Data.Set' di parole sensibili al maiuscolo/minuscolo (compresi "US" ma non "Us" o "us"), e scrivi un controllo di uguaglianza che dice 'corrisponde a xy | isCaseSensitive x || isCaseSensitive y = x == y' e '| altrimenti = toCaseFold x == toCaseFold y' – AndrewC

risposta

2

Se lo stile del confronto è guidato dalla semantica della cosa che viene confrontata, ha senso passare quella semantica con il testo attuale? È inoltre possibile quindi normalizzare se del caso, per evitare il ripetuto passa poi:

data Token = Token CaseSensitive Text -- Text is all lower-case if Insensitive 
    deriving Eq 

e forse definire un costruttore intelligente:

token Sensitive t = Token Sensitive t 
token Insensitive t = Token Insensitive (T.toLower t) 

Ciò implica che l'acronimo "US" non sempre confrontare pari a la parola "noi", ma sembra logico comunque.

È inoltre possibile contrassegnare i valori con qualcosa di più dettagliato come acronimo/parola/... piuttosto che solo Sensitive/Insensitive.

Problemi correlati