haskellari / these

An either-or-both data type, with corresponding hybrid error/writer monad transformer.
117 stars 49 forks source link

Unzip Map and IntMap more strictly #163

Open treeowl opened 3 years ago

treeowl commented 3 years ago

The previous Map (same for IntMap throughout) instance would first map eagerly over tha Map, producing an entire Map full of thunks to apply the unzipWith function. Then it would build two more entire Maps full of thunks to select components of each pair. We can do it eagerly using Data.Biapplicative.traverseBia and a simple pair bifunctor.

treeowl commented 3 years ago

Note: if you really want to be super-lazy, we can at least avoid three entire Maps and needing to worry about whether the resulting Maps even contain selector thunks (or if they can leak space).

unzipWith f = unSBPair . traverseBia (SBPair . blah)
  where
    blah c = let
      {-# NOINLINE fc #-} -- make sure the result of f c is shared
      {-# NOINLINE a #-} -- make sure we get selector thunks
      {-# NOINLINE b #-}
      fc = f c
      (a, b) = fc
    in (a, b)
treeowl commented 3 years ago

I've opened #164 with a version that preserves the precise laziness of the current version but without the leak potential and without building a third map structure.

treeowl commented 3 years ago

(Personally, I like this version better than that one, but it's not my package.)