<p dir="ltr">-1. I think these are good functions, but I don't think base is the place for them. They just don't seem "fundamental" enough. That said, they can be optimized for list fusion based on this implementation, and even use build to fuse the other way. No zipWith implementation will do this.</p>
<p dir="ltr">zipWithAdj f xs = foldr go (`seq` []) xs Nothing where<br>
  go x r Nothing = r (Just x)<br>
  go x r (Just prev) = f prev x : r (Just x)</p>
<div class="gmail_quote">On Apr 13, 2016 3:38 AM, "Roman Cheplyaka" <<a href="mailto:roma@ro-che.info">roma@ro-che.info</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">-1<br>
<br>
zip xs (tail xs) is a simple, well-known idiom. If you think there's an<br>
education problem, you could document and explain it in the haddock for<br>
zip or zipWith.<br>
<br>
As you note yourself, there is no problem with empty lists. If you are<br>
worried about tail, use drop 1 as David suggests.<br>
<br>
On 04/12/2016 11:55 PM, Johan Holmquist wrote:<br>
> I propose adding two new functions to Data.List:<br>
><br>
>     zipConsecutives :: [a] -> [(a,a)]<br>
>     zipConsecutives xs = zip xs (tail xs)<br>
><br>
>     zipConsecutivesWith :: (a -> a -> b) -> [a] -> [b]<br>
>     zipConsecutivesWith f xs = zipWith f xs (tail xs)<br>
><br>
> (with possibly more efficient implementations)<br>
><br>
> The Trac feature request is at<br>
> <a href="https://ghc.haskell.org/trac/ghc/ticket/11815" rel="noreferrer" target="_blank">https://ghc.haskell.org/trac/ghc/ticket/11815</a>.<br>
><br>
><br>
> Why<br>
><br>
> These functions are useful when one wants to process consecutive pairs<br>
> of elements in a sequence, which is not uncommon. The ticket lists<br>
> some examples, reiterated here:<br>
><br>
>     -- diff consecutive elements:<br>
>     diffs = zipConsecutivesWith (flip (-))<br>
><br>
>     -- determine if list is ascending (similar for descending and strict):<br>
>     isAscending = and . zipConsecutivesWith (<=)<br>
><br>
>     -- an old friend of ours:<br>
>     fibs = 1 : 1 : zipConsecutivesWith (+) fibs<br>
><br>
>     -- get the edges of a closed path defined by points (ps):<br>
>     edges ps = zipConsecutivesWith makeEdge (ps ++ take 1 ps)<br>
><br>
><br>
> Why add to Data.List (and base)<br>
><br>
> The definition must either use an extra equation for the empty list case:<br>
><br>
>     zipConsecutives [] = []<br>
>     zipConsecutives xs = zip xs (tail xs)<br>
><br>
> which makes it non practical to define inline at each use site. Or one<br>
> may omit the empty list equation, which is safe (thanks to laziness),<br>
> but that may not be immediately obvious. (It wasn't to me anyway.) The<br>
> tail function is generally considered unsafe so it is not desirable to<br>
> force the user to use it. The proposed functions would offer an<br>
> alternative.<br>
><br>
><br>
> The Data.List module is often imported unqualified, so new identifiers<br>
> may cause collissions. I do find it rather unlikely that the proposed<br>
> names would cause such problems, however.<br>
><br>
><br>
> Deadline for discussion: 2016-05-31.<br>
><br>
><br>
> _______________________________________________<br>
> Libraries mailing list<br>
> <a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
><br>
<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>