8
votes

Changer l'élément de la liste s'il contient une condition ou en ajoute un nouveau si ce n'est le cas, à l'aide de données.lens

J'ai une liste d'enregistrements et j'ai besoin d'une fonction qui recherche la liste d'un enregistrement avec un nom donné et modifie la valeur de cet enregistrement ou si aucun enregistrement correspond à une nouvelle enregistrement sur le résultat résultant. liste. Voici mon code jusqu'à présent: XXX

Cela fonctionne bien, mais je me demande s'il y a une manière plus directe d'écrire cela en utilisant data.lens (sans le si -Construction)? Aussi, dois-je écrire la fonction _Find ou y at-il quelque chose d'équivalent dans la bibliothèque?

mise à jour : voici un gist de la source à Expériment: https://gist.github.com/skoschnicke/5795863


0 commentaires

3 Réponses :


2
votes

Je ne sais pas, mais vous pouvez écrire un peu comme xxx


0 commentaires

2
votes

donc, _Find n'est pas réellement un trafersal : xxx

c'est le même sens filtré N'est-ce pas une traversée.

Obtenir une partie peut être imitée avec filtré (Ça va ici depuis pli n'a pas de lois): xxx

maintenant, en supposant que "plus directe voie" est un peu intelligent Traversal : Non, ce n'est pas possible, Traversal S ne peut pas modifier la structure de la chose traversée.


2 commentaires

Je pense que je dois en lire d'autres sur les lentilles pour comprendre cela, mais merci d'avoir souligné cela! Je suppose qu'il n'y a rien de tel qu'un Traversal qui peut changer la structure de la chose traversée?


C'est exact, il n'y a rien de tel. Le problème est que vous ne pouvez pas avoir de bonnes lois pour cela.



2
votes

Que diriez-vous:

changeOrCreate :: String -> (Int -> Int) -> [SomeRec] -> [SomeRec]
changeOrCreate nameToSearch valModifier = 
  pos . val %~ valModifier
  & outside (filtered (not . has pos)) %~ (. newRec)
  where
    pos :: Traversal' [SomeRec] SomeRec
    pos = taking 1 (traversed . filtered (anyOf name (== nameToSearch)))
    newRec = (SomeRec nameToSearch 0 :)


3 commentaires

Donc, un prisme me permet de changer la liste? Je pense que je dois tester cela pour comprendre complètement, le fera demain!


Fonctionne bien! Mais autant que je sache, avec l'utilisation de filtré , POS n'est pas valide Traversal plus, non? Celles-ci ne sont généralement pas compostables avec d'autres travers.


Ce n'est en effet pas un achatsal valide si vous l'utilisez pour modifier le champ nom et que le prédicat ne contienne plus ("Règles" peut casser, comme démontré la réponse de Matvey) , mais sinon, il est composé d'autres travers.