semialign 1.3.1.1 → 1.4
raw patch · 3 files changed
+97/−4 lines, 3 files
Files
- CHANGELOG.md +11/−0
- semialign.cabal +1/−1
- src/Data/Semialign/Internal.hs +85/−3
CHANGELOG.md view
@@ -1,3 +1,14 @@+# 1.4++- Reorder class hierarchy. `Unzip` is now at the bottom, right above `Functor`.+ There are two ways things may break:+ - You may need to add `Unzip` instance if you haven't one already, for example:+ `instance Unzip ((->) e) where unzip = unzipDefault` was added in this patch.+ - `Unzip f` doesn't imply whole hierarchy, so you may need to change `Unzip f` to `Zip f`+ in the constraints of some of your functions.+- Relax laws of Unalign allowing list-like instances.+ - Add `Unalign []` and `Unalign Vector` instances.+ # 1.3.1 - Support GHC-8.6.5...GHC-9.10.1
semialign.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: semialign-version: 1.3.1.1+version: 1.4 synopsis: Align and Zip type-classes from the common Semialign ancestor.
src/Data/Semialign/Internal.hs view
@@ -121,7 +121,7 @@ -- ≡ mapMaybe justHere (toList (align x y)) -- @ ---class Functor f => Semialign f where+class Unzip f => Semialign f where -- | Analogous to @'zip'@, combines two structures by taking the union of -- their shapes and using @'These'@ to hold the elements. align :: f a -> f b -> f (These a b)@@ -156,10 +156,18 @@ -- == Laws -- -- @--- uncurry align (unalign xs) ≡ xs -- unalign (align xs ys) ≡ (xs, ys) -- @ --+-- Previously 'Unalign' included a right inverse law+--+-- @+-- uncurry align (unalign xs) ≡ xs+-- @+--+-- But this law was removed in 1.4 to allow list-like instances,+-- where unalign necessarily loses some information.+-- -- == Compatibility note -- -- In version 1 'unalign' was changed to return @(f a, f b)@ pair,@@ -295,7 +303,7 @@ -- -- For sequence-like types this holds, but for Map-like it doesn't. ---class Zip f => Unzip f where+class Functor f => Unzip f where unzipWith :: (c -> (a, b)) -> f c -> (f a, f b) unzipWith f = unzip . fmap f @@ -337,6 +345,12 @@ -- base ------------------------------------------------------------------------------- +-- |+--+-- @since 1.4+instance Unzip ((->) e) where+ unzip = unzipDefault+ instance Semialign ((->) e) where align f g x = These (f x) (g x) alignWith h f g x = h (These (f x) (g x))@@ -402,6 +416,16 @@ instance Unzip [] where unzip = Prelude.unzip +-- |+--+-- @since 1.4+instance Unalign [] where+ unalign = Prelude.foldr f ([], []) where+ f :: These a b -> ([a], [b]) -> ([a], [b])+ f (This x) ~(xs, ys) = (x : xs, ys)+ f (That y) ~(xs, ys) = ( xs, y : ys)+ f (These x y) ~(xs, ys) = (x : xs, y : ys)+ instance SemialignWithIndex Int [] instance ZipWithIndex Int [] instance RepeatWithIndex Int []@@ -423,6 +447,10 @@ unzip (ZipList xs) = (ZipList ys, ZipList zs) where (ys, zs) = unzip xs +instance Unalign ZipList where+ unalign (ZipList xs) = (ZipList ys, ZipList zs) where+ (ys, zs) = unalign xs+ instance SemialignWithIndex Int ZipList instance ZipWithIndex Int ZipList instance RepeatWithIndex Int ZipList@@ -661,6 +689,13 @@ ------------------------------------------------------------------------------- -- Based on the Data.Vector.Fusion.Stream.Monadic zipWith implementation++-- |+--+-- @since 1.4+instance Monad m => Unzip (Stream m) where+ unzip = unzipDefault+ instance Monad m => Align (Stream m) where nil = Stream.empty @@ -688,9 +723,39 @@ _ -> Skip (sa, sb, Nothing, False) #endif +-- |+--+-- @since 1.4+instance Monad m => Unalign (Stream m) where+ unalign (Stream stepa s) = (Stream stepb s, Stream stepc s)+ where+ stepb i = do+ r <- stepa i+ return $ case r of+ Done -> Done+ Skip j -> Skip j+ Yield (This x) j -> Yield x j+ Yield (These x _) j -> Yield x j+ Yield (That _) j -> Skip j++ stepc i = do+ r <- stepa i+ return $ case r of+ Done -> Done+ Skip j -> Skip j+ Yield (This _) j -> Skip j+ Yield (These _ y) j -> Yield y j+ Yield (That y) j -> Yield y j+ instance Monad m => Zip (Stream m) where zipWith = Stream.zipWith +-- |+--+-- @since 1.4+instance Monad m => Unzip (Bundle m v) where+ unzip = unzipDefault+ instance Monad m => Align (Bundle m v) where nil = Bundle.empty @@ -701,6 +766,15 @@ instance Monad m => Zip (Bundle m v) where zipWith = Bundle.zipWith +-- |+--+-- @since 1.4+instance Monad m => Unalign (Bundle m v) where+ unalign Bundle { sElems = xys, sSize = n } =+ (Bundle.fromStream xs (Bundle.toMax n), Bundle.fromStream ys (Bundle.toMax n))+ where+ ~(xs, ys) = unalign xys+ instance Semialign V.Vector where alignWith = alignVectorWith @@ -712,6 +786,14 @@ instance Unzip V.Vector where unzip = V.unzip++-- |+--+-- @since 1.4+instance Unalign V.Vector where+ -- TODO: it would be more efficient to do unalign imperatively.+ unalign xys = (unstream xs, unstream ys) where+ ~(xs, ys) = unalign (stream xys) alignVectorWith :: (Vector v a, Vector v b, Vector v c) => (These a b -> c) -> v a -> v b -> v c