Potential space leak in transpose

Ryan Reich ryan.reich at gmail.com
Fri May 15 00:08:57 UTC 2020


Hopefully I'm not fooling myself...how about this?

---
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose (r1 : rrest) = zipWith' (:) (:[]) id r1 (transpose rrest)

zipWith' :: (a -> b -> c) -> (a -> c) -> (b -> c) -> ([a] -> [b] -> [c])
zipWith' _ _ fb [] bs = fb <$> bs
zipWith' _ fa _ as [] = fa <$> as
zipWith' f fa fb (a : as) (b : bs) = f a b : zipWith' f fa fb as bs

main = do
  mapM_ (print . transpose)
    [
      [[1,2,3]],
      [[1,2,3],[4,5,6]],
      [[1,2,3],[4,5,6],[7,8,9]],
      [[10,11],[20],[],[30,31,32]]
    ]
---

I see the output:
---
[[1],[2],[3]]
[[1,4],[2,5],[3,6]]
[[1,4,7],[2,5,8],[3,6,9]]
[[10,20,30],[11,31],[32]]
---

which is correct (the last example is the one from the haddocks).

I was concerned that the definition of zipWith' (which is akin to the Map
function unionWith) is not compatible with the build/fold fusion rule, but
the implementation of zipWith itself is basically the same.

Ryan

On Thu, May 14, 2020 at 1:17 PM David Feuer <david.feuer at gmail.com> wrote:

> Right. I still think it might be the right thing to do, though. I'm not a
> big fan of general-purpose library functions that have any unnecessary
> memory leak hazard. The biggest counterargument is that real code is
> unlikely to run into that problem.
>
> On Thu, May 14, 2020, 3:35 PM Ryan Reich <ryan.reich at gmail.com> wrote:
>
>> My suggestion was much less sophisticated even than that, and is
>> basically what David answered with fusion. Also according to his answer,
>> the original code of transpose lacks the laziness that unzip's actual
>> implementation would provide.
>>
>> I think what that means is that his concern over allocating extra pairs
>> is about the ones created internally by unzip when it builds the lazy
>> heads-and-tails accessors.
>>
>> On Thu, May 14, 2020, 03:27 Andreas Abel <andreas.abel at ifi.lmu.de> wrote:
>>
>>> On 2020-05-13 22:27, Ryan Reich wrote:
>>> > Why not just inline the definition of unzip and hand-optimize away the
>>> > pairs?
>>>
>>> Isn't this what the original code of transpose is doing?
>>>
>>> > On Tue, May 12, 2020, 10:24 David Feuer <david.feuer at gmail.com
>>> > <mailto:david.feuer at gmail.com>> wrote:
>>> >
>>> >     Also, the more eager list allocation can increase residency, but I
>>> >     don't think it can cause a leak.
>>> >
>>> >     On Tue, May 12, 2020, 9:48 AM David Feuer <david.feuer at gmail.com
>>> >     <mailto:david.feuer at gmail.com>> wrote:
>>> >
>>> >         The cost of allocating the extra pairs.
>>> >
>>> >         On Tue, May 12, 2020, 5:11 AM Andreas Abel
>>> >         <andreas.abel at ifi.lmu.de <mailto:andreas.abel at ifi.lmu.de>>
>>> wrote:
>>> >
>>> >               > I don't know how much that'll cost in practice.
>>> >
>>> >             What costs are you worried about?
>>> >
>>> >             On 2020-05-12 00:08, David Feuer wrote:
>>> >              > In Data.List, we define
>>> >              >
>>> >              > transpose :: [[a]] -> [[a]]
>>> >              > transpose [] = []
>>> >              > transpose ([] : xss) = transpose xss
>>> >              > transpose ((x : xs) : xss) = (x : [h | (h : _) <- xss])
>>> :
>>> >             transpose (xs
>>> >              > : [t | (_ : t) <- xss])
>>> >              >
>>> >              > The potential difficulty is that we essentially mapMaybe
>>> >             over the xss
>>> >              > list twice in the third case. So we hang on to the heads
>>> >             where we need
>>> >              > the tails and the tails where we need the heads. We
>>> could
>>> >             fix that with
>>> >              > something like this:
>>> >              >
>>> >              > transpose ((x : xs) : xss) = (x : fronts) : transpose
>>> (xs
>>> >             : rears)
>>> >              >    where
>>> >              >      (fronts, rears) = unzip [(h,t) | (h : t) <- xss]
>>> >              >
>>> >              > I don't know how much that'll cost in practice.
>>> >              >
>>> >              > _______________________________________________
>>> >              > Libraries mailing list
>>> >              > Libraries at haskell.org <mailto:Libraries at haskell.org>
>>> >              >
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>> >              >
>>> >
>>> >     _______________________________________________
>>> >     Libraries mailing list
>>> >     Libraries at haskell.org <mailto:Libraries at haskell.org>
>>> >     http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>> >
>>> >
>>> > _______________________________________________
>>> > Libraries mailing list
>>> > Libraries at haskell.org
>>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>> >
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20200514/2b53d74d/attachment.html>


More information about the Libraries mailing list