I have a list of records and need a function which searches the list for a record with a given name and modify the value of this record OR if no record matches append a new record to the resulting list. Here is my code so far:
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)]
It works fine, but I'm wondering if there is a more direct way of writing this using Data.Lens
(without the if
-construct)? Also, do I have to write the _find
function or is there something equivalent in the library?
Update: Here is a Gist of the source to experiment: https://gist.github.com/SKoschnicke/5795863
Prism
lets me change the list? I think I have to test that to understand completly, will do that tomorrow! – Shed