另一种选择是使用
lens包。这可以避免显式递归,并使您在可以操作的数据结构上保持非常灵活。您可以使用
elements遍历。它需要一个
Int -> Bool
函数来决定要操作哪些索引。双倍偶数索引或奇数索引。
> over (elements even) (*2) [8,7,6,5]
[16,7,12,5]
> over (elements odd) (*2) [8,7,6,5]
[8,14,6,10]
或者将每个第三个元素加倍:
> over (elements (\n -> mod n 3 == 0)) (*2) [8,7,6,5]
[16,7,6,10]
不仅仅是列表
这个技巧适用于任何具有Traversable实例的数据类型。
例如,考虑containers中的标准树数据类型。
> import Data.Tree
> let tree = Node 1 [Node 2 [Node 3 [], Node 4 []], Node 5 [Node 6 []]]
> let prettyTree = putStrLn . drawTree . fmap show
> prettyTree tree
1
|
+- 2
| |
| +- 3
| |
| `- 4
|
`- 5
|
`- 6
> prettyTree $ over (elements even) (*2) tree
2
|
+- 2
| |
| +- 6
| |
| `- 4
|
`- 10
|
`- 6
您的问题。
The lens package has a number of functions that help with handling recursion with out being explicit.
The lens is concise, though some do not yet considered it idiomatic. I have not tested the bigO of the above functions. My understanding is that it will depend on the bigO of the traversable instance for the datatype you are using.
The list instance in the Traversable module looks straightforward and should meet your expectations.:
instance Traversable [] where
{-# INLINE traverse #-}
traverse f = Prelude.foldr cons_f (pure [])
where cons_f x ys = (:) <$> f x <*> ys
I am not sure what you are asking for here.