Kayıtların bir listesi var ve belirli bir ada sahip bir kayıt için listeyi araştıran ve değeri değiştiren bir işleve ihtiyacım var Bu kayıttan VEYA, hiçbir kayıt eşleşmesi sonuç listesine yeni bir kayıt eklerse. Düzgün çalışırBazı koşullara karşı koruysa veya yeni bir tane eklerse, öğenin içeriğini değiştirirseniz, Data.Lens
import Control.Lens
import Control.Applicative ((<$>), pure)
import Data.List (any)
data SomeRec = SomeRec { _name :: String, _val :: Int }
$(makeLenses ''SomeRec)
_find :: (a -> Bool) -> Simple Traversal [a] a
_find _ _ [] = pure []
_find pred f (a:as) = if pred a
then (: as) <$> f a
else (a:) <$> (_find pred f as)
changeOrCreate :: [SomeRec] -> String -> (Int -> Int) -> [SomeRec]
changeOrCreate recs nameToSearch valModifier =
if (any (\r -> r^.name == nameToSearch) recs)
then over (_find (\r -> r^.name == nameToSearch)) (over val valModifier) recs
else recs ++ [SomeRec nameToSearch (valModifier 0)]
ancak (if
-Construct olmadan) Data.Lens
kullanarak bu yazı daha doğrudan bir yol olup olmadığını merak ediyorum: İşte benim kod şimdiye kadar mı? Ayrıca, _find
işlevini yazmalı mıyım yoksa kitaplıkta eşdeğer bir şey var mı?
Güncelleme: İşte kaynağının Gist denemektir: https://gist.github.com/SKoschnicke/5795863
Yani, bir 'Prism' listeyi değiştirmeme izin veriyor? Bunu anlayabilmek için bunu test etmem gerektiğini düşünüyorum, bunu yarın yapacak! –
Güzel çalışıyor! Ama anladığım kadarıyla, "filtrelenmiş" kullanımıyla, "pos" artık geçerli değil "Traversal", değil mi? Bunun için genellikle diğer traversler ile birleştirilemez. –
Gerçekten de 'isim' alanını değiştirmek için kullanırsanız ve bu nedenle yüklemenin artık kullanılmamasını sağlarsanız ('kurallar', Matvey'in yanıtında gösterildiği gibi bozulabilir) geçerli bir Traversal işlevi değildir, ancak aksi halde diğerleriyle birleştirilebilir. dolaşımları. – yairchu