Je plonge toujours plus profondément dans les lentilles de Kmett; Aujourd'hui, j'essaye d'écrire des parcours personnalisés, jusqu'à présent j'ai réussi à composer en créant des traversées existantes pour en créer de nouvelles, mais je fais quelque chose d'un peu plus compliqué et je suis coincé. J'écris un éditeur de texte et j'ajoute juste des curseurs multiples, à l'origine chaque tampon avait un curseur et avait un objectif pour le mettre au point, maintenant je généraliser à une liste de curseurs et je veux une traversée sur le liste. L'astuce est que dans le cas précédent mon objectif a fait une validation à l'intérieur du setter pour s'assurer qu'un curseur a été serré pour tenir dans la plage valide du texte du tampon. Il ressemblait à ceci:Rédaction d'une Traversée plus complexe (Lentilles)
clampCursor :: Text -> Cursor -> Cursor
cursor :: Lens' Buffer Cursor
cursor = lens getter setter
where getter buf = buf^.curs
setter buf new = let txt = buf^.text
in buf & curs .~ clampCursor txt new
Notez comment il utilise les informations de texte du contexte du tampon pour créer une lentille sur le curseur; (Aussi, j'aimerais entendre parler de façons plus propres de faire cela au lieu de faire des lentilles personnalisées si quelqu'un a des suggestions, je me suis retrouvé à le faire beaucoup). Maintenant que j'ai plusieurs curseurs, j'ai besoin de le transformer en Traversal ', mais bien sûr je ne peux pas définir de traversée en utilisant la méthode lens getter setter
; En regardant autour de la façon de définir traversals je lis ceci tutorial; Lequel des états suivants:
Question: Comment créer des traversées?
Réponse: Il existe trois principales façons de créer traversals primitifs:
- traverse est un Traversal » que vous obtenez pour tout type qui implémente Traversable
- Chaque Lens sera également de type vérification comme Traversal «
- Vous pouvez utiliser le modèle Haskell pour générer en utilisant les makePrisms de Traversal puisque chaque prisme » est aussi un Traversal »(non couvert dans ce tutoriel)
Aucune de ces méthodes n'aide vraiment ici; J'ai aussi vu le style où vous créez une traversée en utilisant un style applicatif, mais ça m'a toujours dérouté et je ne sais pas vraiment comment je l'utiliserais dans ce cas pour obtenir ce que je veux. Je suppose que je pourrais écrire un Lens' Buffer [Cursor]
qui mappe sur les curseurs dans le setter pour effectuer la validation et ensuite traverser cette liste, mais je pense qu'il doit y avoir un moyen de le faire dans la traversée APRÈS la traversée (quand chaque l'élément unique est focalisé) d'une manière ou d'une autre. Peut-être qu'il y a une meilleure façon de le faire entièrement;
Toujours à la recherche de tout ce que je peux sur les traversées, donc toutes les explications sont appréciées! Merci!
EDIT: @dfeuer a souligné que lorsque vous faites ce genre de validation vous vous retrouvez avec des lentilles non valides, j'aime vraiment l'interface propre qu'il fournit pour les faire à l'intérieur de l'objectif; et pour autant que je le sache, puisque la validation est idempotente, cela ne devrait pas causer de problème réel, mais je suis ouvert à des suggestions sur la façon de faire mieux.
Vous avez déjà un peu d'un problème: grâce au serrage, votre 'Lens 'n'est pas tout à fait une lentille respectueuse de la loi. Pouvez-vous donner plus d'informations sur ce qu'est un 'Cursor' et comment est-il utilisé? Votre configuration actuelle me semble un peu étrange. Je n'ai pas tendance à penser qu'un curseur fait partie d'un tampon. Je soupçonne que ce que vous voulez vraiment, c'est quelque chose de plus comme une collection de "pointeurs" ressemblant à des lentilles dans un tampon. – dfeuer
Hrmm, je suppose que c'est vrai; Y a-t-il une meilleure façon de faire la validation là où l'interface est propre mais respectueuse des lois? J'ai toujours pensé aux setters comme où la validation devrait être effectuée. Fondamentalement, un curseur est un décalage dans le fichier qui conserve la trace de l'endroit où les opérations futures doivent être effectuées, par ex. supprimer des caractères, insérer du texte, etc. "Buffer" dans ce cas fait référence à la terminologie Vim d'une représentation de texte éditable. Dans mon cas, chaque tampon contient un ensemble de curseurs.J'aimerais faire tout en utilisant des pointeurs de type objectif, mais vous enfreignez d'autres lois de l'objectif lorsque vous essayez de le faire: P –
Je voudrais également faire plus de transformations sur la liste de curseurs quand elle est définie; par exemple, je voudrais les trier et supprimer les doublons aussi bien. –