我有一个记录列表,需要一个函数来搜索具有给定名称的记录,并修改该记录的值或者如果没有匹配的记录,则将新记录附加到结果列表中。这是我的代码:
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)]
它可以正常工作,但我想知道是否有更直接的方法使用
Data.Lens
(不使用 if
构造)来编写它?此外,我是否必须编写 _find
函数,还是库中存在等效的函数?更新:这里有一个源代码 Gist 供您实验:https://gist.github.com/SKoschnicke/5795863。