如果元素不在那里,如何将元素添加到列表中?'?

时间:2017-09-24 12:35:00

标签: list haskell lens

我们说我有一个列表[A]。如果满足某些谓词,我想更新列表的特定元素。但如果没有这样的元素,我想先将元素添加到列表中。我目前的解决方案是手动编写将元素插入列表的函数(如果它不存在)然后使用filtered遍历来更新我的元素。像这样:

-- inserts element to list if there's no a single element 
-- which satisfies given predicate 
insertIfNot :: (a -> Bool) -> a -> [a] -> [a]
insertIfNot _ e []       = [e]
insertIfNot p e l@(x:xs) = if p x then l else x : insertIfNot p e xs

functionIWantToWrite :: [A] -> [A]
functionIWantToWrite = modifyItem . addEmptyItem
  where
    addEmptyItem = insertIfNot myPredicate item
    modifyItem   = each.filtered myPredicate %~ myUpdate

我想知道是否有更好(更短,更惯用)的解决方案?如果可能的话,我会很感激只使用microlens系列软件包的解决方案。

1 个答案:

答案 0 :(得分:0)

你应该可以使用has来缩短它:

functionIWantToWrite :: [A] -> [A]
functionIWantToWrite = modifyItem . addEmptyItem
  where
    _items = filtered myPredicate
    addEmptyItem list | has _items list = list
                      | otherwise       = item : list 
    modifyItem = each . _items %~ myUpdate

如果您真的想缩短它,您可以使用Monoid m => Applicative (m,)实例左右将其作为单个遍历来获取,例如

accAny :: (x -> Bool) -> (x -> x) -> x -> (Any, x)
accAny pred fn x = (Any b, if b then fn x else x)
  where b = pred x

functionIWantToWrite list = handle . traverse . accAny myPredicate myUpdate $ list
  where handle (Any True, list) = list
        handle (_, list) = item : list