Alors que l'opinion générale de la communauté Haskell semble être qu'il est toujours préférable d'utiliser Text
au lieu de String
, le fait que les API de la plupart des bibliothèques maintenues sont toujours String
-oriented confond l'enfer hors de moi. D'autre part, il y a projets notables , qui considèrent String
comme une erreur tout à fait et fournissent un Prelude
avec toutes les instances de String
- orientées fonctions remplacées par leurs équivalents Text
-.
Y a-t-il donc des raisons pour que les gens continuent à écrire des API orientées String
à l'exception de la compatibilité avec Prelude en amont et en standard et les "interfaces de commutation"? Y a-t-il éventuellement d'autres inconvénients à Text
par rapport à String
?
En particulier, cela m'intéresse parce que je conçois une bibliothèque et essaie de décider quel type utiliser pour exprimer les messages d'erreur.
Ma supposition sans réserve est que la plupart des rédacteurs de bibliothèques ne veulent pas ajouter plus de dépendances que nécessaire. Étant donné que les chaînes font littéralement partie de chaque distribution Haskell (cela fait partie de la norme de langage!), Il est beaucoup plus facile d'être adopté si vous utilisez des chaînes et n'exigez pas que vos utilisateurs trient les distributions de texte du piratage.
C'est l'une de ces "erreurs de conception" avec lesquelles vous n'avez qu'à vivre, à moins que vous ne puissiez convaincre la plupart de la communauté de passer la nuit. Regardez simplement combien de temps il a fallu pour que Applicative soit une superclasse de Monad - un changement relativement mineur mais très recherché - et imaginez combien de temps il faudrait pour remplacer toutes les choses String par Text.
Pour répondre à votre question plus spécifique: j'irais avec String à moins que vous n'obteniez des avantages de performances notables en utilisant Text. Les messages d'erreur sont généralement de petites choses ponctuelles, donc l'utilisation de String ne devrait pas être un gros problème.
D'un autre côté, si vous êtes le genre de puriste idéologique qui évite le pragmatisme pour l'idéalisme, optez pour le texte.
* Je mets les erreurs de conception entre guillemets effrayants car les chaînes en tant que liste de caractères sont une propriété soignée qui les rend faciles à raisonner et à intégrer avec d'autres fonctions d'exploitation de liste existantes.
Si votre API vise à traiter de grandes quantités de données orientées caractères et/ou divers encodages, alors votre API doit utiliser Texte.
Si votre API est principalement destinée à traiter les petites chaînes uniques, l'utilisation du type intégré String devrait être correcte.
L'utilisation de String pour de grandes quantités de texte fera que les applications utilisant votre API consomment beaucoup plus de mémoire. Son utilisation avec des encodages étrangers pourrait sérieusement compliquer l'utilisation en fonction du fonctionnement de votre API.
La chaîne est assez chère (au moins 5N mots où N est le nombre de Char dans la chaîne). Un mot est le même nombre de bits que l'architecture du processeur (ex. 32 bits ou 64 bits): http://blog.johantibell.com/2011/06/memory-footprints-of-some-common-data .html
Il y a au moins trois raisons d'utiliser [Char] dans les petits projets.
[Char]
ne dépend d'aucun personnel obscur, comme les pointeurs étrangers, la mémoire brute, les tableaux bruts, etc. qui peuvent fonctionner différemment sur différentes plates-formes ou même être indisponibles
[Char]
est la lingua franka à haskell. Il existe au moins trois méthodes "efficaces" pour gérer les données unicode dans haskell: utf8-bytestring
, Data.Text.Text
et Data.Vector.Unboxed.Vector Char
, chacun nécessitant un traitement supplémentaire.
en utilisant [Char]
on accède à toute la puissance de []
monad, y compris de nombreuses fonctions spécifiques (des paquets de chaînes alternatifs essaient de l'aider, mais quand même)
Personnellement, je considère tf16 - basé sur Data.Text
l'une des désignations les plus discutables de la communauté haskell, puisque tf16 combine les défauts de l'encodage tf8 et tf32 sans avoir aucun de ses avantages .
Je ne pense pas qu'il y ait une seule raison technique pour que String reste. Et je peux en voir plusieurs pour que ça aille.
Dans l'ensemble, je dirais d'abord que dans le cas du texte/chaîne, il n'y a qu'une seule meilleure solution:
Les performances des cordes sont mauvaises, tout le monde est d'accord là-dessus
Le texte n'est pas difficile à utiliser. Toutes les fonctions couramment utilisées sur String sont disponibles sur Text, plus quelques-unes plus utiles dans le contexte des chaînes (substitution, remplissage, encodage)
avoir deux solutions crée une complexité inutile à moins que toutes les fonctions de base ne soient rendues polymorphes. Preuve: il y a SO questions sur le sujet des conversions automatiques . Donc est un problème.
Une solution est donc moins complexe que deux, et les défauts de String la feront disparaître à terme. Le plus tôt sera le mieux !
Je me demande si Data.Text est toujours plus efficace que Data.String ???
"contre" par exemple est O(1) pour les chaînes et O(n) pour le texte. Ajouter est O(n) pour les chaînes et O (n + m) pour les textes stricts. De même,
let foo = "foo" ++ bigchunk
bar = "bar" ++ bigchunk
est plus efficace en termes d'espace pour les chaînes que pour les textes stricts.
Un autre problème non lié à l'efficacité est la correspondance de modèles (code perspicuous) et la paresse (prévisible par caractère dans les chaînes, en quelque sorte l'implémentation dépend du texte paresseux).
Les textes sont évidemment bons pour les séquences de caractères statiques et pour la modification sur place. Pour d'autres formes d'édition structurelle, Data.String peut présenter des avantages.