2014-07-02 7 views
5

Ich muss oft Vergleiche von Data.Text-Werten mit unterschiedlichen Anforderungen für die Groß-/Kleinschreibung - das kommt häufig vor, wenn ich chatter für NLP-Aufgaben verwenden.Vergleiche zwischen Groß- und Kleinschreibung für Data.Text?

Wenn ich zum Beispiel Token für Informationsextrahierungsaufgaben suche, muss ich häufig nach Gleichheitsbeziehungen suchen, die weniger restriktiv sind als die Standard-String-Gleichheit. Groß-/Kleinschreibung ist die häufigste dieser Änderungen, aber oft eine Funktion des spezifischen Tokens. Ein Begriff wie "aktivieren" könnte normalerweise Kleinbuchstaben sein, aber wenn es das erste Wort in einem Satz ist, wird es mit einem führenden Kapital beginnen, oder wenn es in einem Titeltext verwendet wird, kann es in Großbuchstaben oder groß geschrieben werden Vergleiche, die den Fall ignorieren, sind sinnvoll. Umgekehrt hat ein Akronym (z. B. "US") unterschiedliche Semantiken, abhängig von der Großschreibung.

Das ist alles zu sagen, dass ich nicht leicht einen Typklassenwrapper für jede Gleichheitsklasse erstellen kann, da es ein wertgesteuerter Aspekt ist. (so sieht das case-insensitive Paket nicht so aus, als würde es funktionieren).

Bisher bin ich toLower mit einer kanonischen Darstellung zu machen, und Vergleichen dieser Darstellungen, damit ich kundenspezifische Versionen von Textvergleichsfunktionen erstellen können, die eine Empfindlichkeit Flagge nehmen, zum Beispiel:

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

Aber ich bin besorgt, dass dies zusätzliche Passagen über den Eingabetext erfordert. Ich könnte mir das in einigen Fällen vorstellen, aber wahrscheinlich nicht alle (zB: T.isuffixOf, T.isInfixOf).

Gibt es einen besseren Weg, dies zu tun?

+5

Sie sollten 'toCaseFold' anstelle von' toLower' für Vergleiche verwenden, bei denen die Groß-/Kleinschreibung nicht berücksichtigt wird. Vielleicht ist das nicht so wichtig, wenn Sie sicher sind, dass der ganze Text Englisch ist, aber es ist immer noch eine gute Angewohnheit, den allgemeineren Ansatz zu verwenden. – Carl

+0

Möglicherweise könnten Sie eine Top-Level-Funktion 'isCaseSensitive' verwenden, vielleicht mit einem' Data.Set' von Groß- und Kleinschreibung (einschließlich "US" aber nicht "Us" oder "uns"), und schreiben Sie eine Gleichheitsprüfung, die besagt 'stimmt mit xy | überein isCaseSensitive x || isCaseSensitive y = x == y' und '| andernfalls = toCaseFold x == toCaseFold y' – AndrewC

Antwort

2

Wenn der Stil des Vergleichs durch die Semantik des zu vergleichenden Dings getrieben wird, macht es Sinn diese Semantiken mit dem eigentlichen Text zu umgehen? Sie können auch dann normalisieren, wo angebracht, die wiederholt zu vermeiden, geht später:

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

und vielleicht einen Smart-Konstruktor definieren:

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

Dies bedeutet, dass die Abkürzung „US“ wird nicht immer gleich vergleichen das Wort "uns", aber das scheint sowieso logisch.

Sie können die Werte auch mit etwas detaillierteren wie Akronym/Word/... anstatt nur Sensitive/Insensitive markieren.

Verwandte Themen