11{-# LANGUAGE CPP #-}
22{-# LANGUAGE DeriveFunctor #-}
3+ {-# LANGUAGE DeriveFoldable #-}
4+ {-# LANGUAGE DeriveTraversable #-}
35{-# LANGUAGE FlexibleInstances #-}
46{-# LANGUAGE FunctionalDependencies #-}
57{-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -14,7 +16,7 @@ module Data.Semialign.Internal where
1416import Prelude
1517 (Bool (.. ), Either (.. ), Eq (.. ), Functor (fmap ), Int , Maybe (.. ),
1618 Monad (.. ), Ord (.. ), Ordering (.. ), String , error , flip , fst , id ,
17- maybe , snd , uncurry , ($) , (++) , (.) )
19+ maybe , snd , uncurry , ($) , (++) , (.) , Traversable , Foldable )
1820
1921import qualified Prelude as Prelude
2022
@@ -590,6 +592,95 @@ instance Biapplicative SBPair where
590592 biliftA2 f g (SBPair (a, b)) (SBPair (c, d)) =
591593 SBPair (f a c, g b d)
592594
595+ -- A copy of (,) with a lazier biliftA2
596+ newtype LBPair a b = LBPair { unLBPair :: (a , b ) }
597+
598+ instance Bifunctor LBPair where
599+ bimap f g (LBPair ab) = LBPair (f a, g b)
600+ where
601+ -- Is this enough? I'm not sure. The danger is if
602+ -- the call inlines and `ab = (p, q)` inlines, but for whatever
603+ -- reason we end up with something like
604+ --
605+ -- a = p
606+ -- b = case ab of (_, q) -> q
607+ --
608+ -- I've seen something vaguely like that before, in Data.List.transpose,
609+ -- but I don't remember the details. If necessary, we can use
610+ -- `GHC.Exts.noinline` on `ab` for `base >= 4.15`, or some kind of shim
611+ -- elsewhere, but then we'll also want a rewrite rule
612+ --
613+ -- bimap f g (LBPair a b) = LBPair (f a, g b)
614+ --
615+ -- for when we get lucky.
616+ {-# NOINLINE a #-}
617+ {-# NOINLINE b #-}
618+ (a, b) = ab
619+
620+ instance Biapplicative LBPair where
621+ bipure a b = LBPair (a, b)
622+ biliftA2 f g (LBPair ab) (LBPair cd) =
623+ LBPair (f a c, g b d)
624+ where
625+ {-# NOINLINE a #-}
626+ {-# NOINLINE b #-}
627+ {-# NOINLINE c #-}
628+ {-# NOINLINE d #-}
629+ (a, b) = ab
630+ (c, d) = cd
631+
632+ newtype UnzipStrictSpineStrictPairs t a =
633+ UnzipStrictSpineStrictPairs { getUnzipStrictSpineStrictPairs :: t a }
634+ deriving (Functor , Foldable , Traversable , Semialign , Align , Zip )
635+
636+ instance (Zip t , Traversable t ) => Unzip (UnzipStrictSpineStrictPairs t ) where
637+ unzipWith = unzipWithStrictSpineStrictPairs
638+
639+ newtype UnzipStrictSpineLazyPairs t a =
640+ UnzipStrictSpineLazyPairs { getUnzipStrictSpineLazyPairs :: t a }
641+ deriving (Functor , Foldable , Traversable , Semialign , Align , Zip )
642+
643+ instance (Zip t , Traversable t ) => Unzip (UnzipStrictSpineLazyPairs t ) where
644+ unzipWith = unzipWithStrictSpineLazyPairs
645+ unzip = unzipStrictSpineLazyPairs
646+
647+ newtype UnzipLazySpineLazyPairs t a =
648+ UnzipLazySpineLazyPairs { getUnzipLazySpineLazyPairs :: t a }
649+ deriving (Functor , Foldable , Traversable , Semialign , Align , Zip )
650+
651+ instance (Zip t , Traversable t ) => Unzip (UnzipLazySpineLazyPairs t ) where
652+ unzipWith = unzipWithLazySpineLazyPairs
653+
654+ unzipWithStrictSpineStrictPairs :: Traversable t
655+ => (c -> (a , b )) -> t c -> (t a , t b )
656+ unzipWithStrictSpineStrictPairs f = unSBPair . traverseBia (SBPair . f)
657+
658+ unzipWithStrictSpineLazyPairs :: Traversable t
659+ => (c -> (a , b )) -> t c -> (t a , t b )
660+ unzipWithStrictSpineLazyPairs f = unSBPair . traverseBia (SBPair . foo)
661+ where
662+ foo c = let
663+ {-# NOINLINE fc #-}
664+ {-# NOINLINE a #-}
665+ {-# NOINLINE b #-}
666+ fc = f c
667+ (a, b) = fc
668+ in (a, b)
669+
670+ unzipStrictSpineLazyPairs :: Traversable t
671+ => t (a , b ) -> (t a , t b )
672+ unzipStrictSpineLazyPairs = unSBPair . traverseBia (SBPair . foo)
673+ where
674+ foo ab = let
675+ {-# NOINLINE a #-}
676+ {-# NOINLINE b #-}
677+ (a, b) = ab
678+ in (a, b)
679+
680+ unzipWithLazySpineLazyPairs :: Traversable t
681+ => (c -> (a , b )) -> t c -> (t a , t b )
682+ unzipWithLazySpineLazyPairs f = unLBPair . traverseBia (LBPair . f)
683+
593684instance Ord k => Unzip (Map k ) where unzip = unzipDefault
594685
595686instance Ord k => Zip (Map k ) where
0 commit comments