Add traverseWithIndex to Data.Sequence

Edward Kmett ekmett at gmail.com
Wed Jan 20 00:17:34 UTC 2016


+1 from me to add something along this line.

Right now I hack around it's lack in lens using a rather inefficient
codepath.

-Edward

On Tue, Jan 19, 2016 at 11:55 AM, David Feuer <david.feuer at gmail.com> wrote:

> Indexed traversals seem to be pretty popular these days, and sequences
> should be able to support them efficiently. At present, the best
> options are
>
> 1. Thread a counter through. This doesn't work well for weird things
> like lazy State.
>
> 2. Use zipWith first to add indices, then traverse. This adds a
> smaller, but still asymptotic, penalty to the same sorts of unusual
> functors, and also adds constant-factor overhead to strict ones that
> the counter threading wouldn't.
>
> I propose the following, modified mechanically from mapWithIndex. It
> should be about as efficient as possible in all cases.
>
> traverseWithIndex :: Applicative f => (Int -> a -> f b) -> Seq a -> f (Seq
> b)
> traverseWithIndex f' (Seq xs') = Seq <$> traverseWithIndexTree (\s
> (Elem a) -> Elem <$> f' s a) 0 xs'
>  where
>   traverseWithIndexTree :: (Applicative f, Sized a) => (Int -> a -> f
> b) -> Int -> FingerTree a -> f (FingerTree b)
>   traverseWithIndexTree _ s Empty = s `seq` pure Empty
>   traverseWithIndexTree f s (Single xs) = Single <$> f s xs
>   traverseWithIndexTree f s (Deep n pr m sf) = sPspr `seq` sPsprm `seq`
>           Deep n <$>
>                traverseWithIndexDigit f s pr <*>
>                traverseWithIndexTree (traverseWithIndexNode f) sPspr m <*>
>                traverseWithIndexDigit f sPsprm sf
>     where
>       sPspr = s + size pr
>       sPsprm = s + n - size sf
>
>   traverseWithIndexDigit :: (Applicative f, Sized a) => (Int -> a -> f
> b) -> Int -> Digit a -> f (Digit b)
>   traverseWithIndexDigit f s (One a) = One <$> f s a
>   traverseWithIndexDigit f s (Two a b) = sPsa `seq` Two <$> f s a <*> f
> sPsa b
>     where
>       sPsa = s + size a
>   traverseWithIndexDigit f s (Three a b c) = sPsa `seq` sPsab `seq`
>                                       Three <$> f s a <*> f sPsa b <*> f
> sPsab c
>     where
>       sPsa = s + size a
>       sPsab = sPsa + size b
>   traverseWithIndexDigit f s (Four a b c d) = sPsa `seq` sPsab `seq`
> sPsabc `seq`
>                           Four <$> f s a <*> f sPsa b <*> f sPsab c
> <*> f sPsabc d
>     where
>       sPsa = s + size a
>       sPsab = sPsa + size b
>       sPsabc = sPsab + size c
>
>   traverseWithIndexNode :: (Applicative f, Sized a) => (Int -> a -> f
> b) -> Int -> Node a -> f (Node b)
>   traverseWithIndexNode f s (Node2 ns a b) = sPsa `seq` Node2 ns <$> f
> s a <*> f sPsa b
>     where
>       sPsa = s + size a
>   traverseWithIndexNode f s (Node3 ns a b c) = sPsa `seq` sPsab `seq`
>                                      Node3 ns <$> f s a <*> f sPsa b
> <*> f sPsab c
>     where
>       sPsa = s + size a
>       sPsab = sPsa + size b
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20160119/ccec5eb0/attachment.html>


More information about the Libraries mailing list