Safe Haskell | Trustworthy |
---|---|

Language | Haskell2010 |

Zipping and aligning of functors with non-uniform shapes.

## Synopsis

- class Functor f => Semialign f where
- class Semialign f => Align f where
- nil :: f a

- class Semialign f => Unalign f where
- unalign :: f (These a b) -> (f a, f b)
- unalignWith :: (c -> These a b) -> f c -> (f a, f b)

- class Semialign f => Zip f where
- full :: a -> f a

- class Semialign f => Unzip f where
- unzipDefault :: Functor f => f (a, b) -> (f a, f b)
- malign :: (Semialign f, Monoid a) => f a -> f a -> f a
- salign :: (Semialign f, Semigroup a) => f a -> f a -> f a
- padZip :: Semialign f => f a -> f b -> f (Maybe a, Maybe b)
- padZipWith :: Semialign f => (Maybe a -> Maybe b -> c) -> f a -> f b -> f c
- lpadZip :: [a] -> [b] -> [(Maybe a, b)]
- lpadZipWith :: (Maybe a -> b -> c) -> [a] -> [b] -> [c]
- rpadZip :: [a] -> [b] -> [(a, Maybe b)]
- rpadZipWith :: (a -> Maybe b -> c) -> [a] -> [b] -> [c]
- alignVectorWith :: (Vector v a, Vector v b, Vector v c) => (These a b -> c) -> v a -> v b -> v c

# Documentation

class Functor f => Semialign f where Source #

Functors supporting a `zip`

and `align`

operations that takes the
intersection and union of non-uniform shapes.

Minimal definition: either `align`

or `alignWith`

and either `zip`

or `zipWith`

.

## Laws

The laws of `align`

and `zip`

resemble lattice laws.
There is a plenty of laws, but they are simply satisfied.

And an addition property if `f`

is `Foldable`

,
which tries to enforce `align`

-feel:
neither values are duplicated nor lost.

*Note:* `join`

f x = f x x

*Idempotency*

join align ≡ fmap (join These) join zip ≡ fmap (join (,))

*Commutativity*

align x y ≡ swap <$> align y x zip x y ≡ swap <$> zip y x

*Associativity*

align x (align y z) ≡ assoc <$> align (align x y) z zip x (zip y z) ≡ assoc <$> zip (zip x y) z

*Absorption*

fst <$> zip xs (align xs ys) ≡ xs toThis <$> align xs (zip xs ys) ≡ This <$> xs where toThis (This a) = This a toThis (These a _) = This a toThis (That b) = That b

*With*

alignWith f a b ≡ f <$> align a b zipWith f a b ≡ f <$> zip a b

*Functoriality*

align (f <$> x) (g <$> y) ≡ bimap f g <$> align x y zip (f <$> x) (g <$> y) ≡ bimap f g <$> zip x y

*Zippyness*

fmap fst (zip x x) ≡ x fmap snd (zip x x) ≡ x zip (fmap fst x) (fmap snd x) ≡ x

*Alignedness*, if `f`

is `Foldable`

toList x ≡ toListOf (folded . here) (align x y) ≡ mapMaybe justHere (toList (align x y))

*Distributivity*

align (zip xs ys) zs ≡ undistrThesePair <$> zip (align xs zs) (align ys zs) distrPairThese <$> zip (align xs ys) zs ≡ align (zip xs zs) (zip ys zs) zip (align xs ys) zs ≡ undistrPairThese <$> align (zip xs zs) (zip ys zs)

*Note*, the following doesn't hold:

distrThesePair <$> align (zip xs ys) zs ≢ zip (align xs zs) (align ys zs)

when `xs = []`

and `ys = zs = [0]`

, then
the left hand side is "only" `[(`

,
but the right hand side is `That`

0, `That`

0)]`[(`

.`That`

0, `These`

0 0)]

align :: f a -> f b -> f (These a b) Source #

Analogous to

, combines two structures by taking the union of
their shapes and using `zip`

to hold the elements.`These`

alignWith :: (These a b -> c) -> f a -> f b -> f c Source #

Analogous to

, combines two structures by taking the union of
their shapes and combining the elements with the given function.`zipWith`

zip :: f a -> f b -> f (a, b) Source #

Combines to structures by taking the intersection of their shapes and using pair to hold the elements.

zipWith :: (a -> b -> c) -> f a -> f b -> f c Source #

Combines to structures by taking the intersection of their shapes and combining the elements with the given function.

## Instances

class Semialign f => Align f where Source #

## Instances

Align [] Source # | |

Defined in Data.Semialign.Internal | |

Align Maybe Source # | |

Defined in Data.Semialign.Internal | |

Align ZipList Source # | |

Defined in Data.Semialign.Internal | |

Align IntMap Source # | |

Defined in Data.Semialign.Internal | |

Align Seq Source # | |

Defined in Data.Semialign.Internal | |

Align Vector Source # | |

Defined in Data.Semialign.Internal | |

(Eq k, Hashable k) => Align (HashMap k) Source # | |

Defined in Data.Semialign.Internal | |

Ord k => Align (Map k) Source # | |

Defined in Data.Semialign.Internal | |

Align (Proxy :: Type -> Type) Source # | |

Defined in Data.Semialign.Internal | |

Monad m => Align (Stream m) Source # | |

Defined in Data.Semialign.Internal | |

Monad m => Align (Bundle m v) Source # | |

Defined in Data.Semialign.Internal | |

(Align f, Align g) => Align (Product f g) Source # | |

Defined in Data.Semialign.Internal | |

(Align f, Semialign g) => Align (Compose f g) Source # | |

Defined in Data.Semialign.Internal |

class Semialign f => Unalign f where Source #

Alignable functors supporting an "inverse" to `align`

: splitting
a union shape into its component parts.

## Laws

uncurry align (unalign xs) ≡ xs unalign (align xs ys) ≡ (xs, ys)

## Compatibility note

In version 1 `unalign`

was changed to return `(f a, f b)`

pair,
instead of `(f (Just a), f (Just b))`

. Old behaviour can be achieved with
if ever needed.

`>>>`

([Just 'a',Nothing,Just 'c'],[Nothing,Just 'b',Just 'd'])`unzipWith (unalign . Just) [This 'a', That 'b', These 'c' 'd']`

unalign :: f (These a b) -> (f a, f b) Source #

unalignWith :: (c -> These a b) -> f c -> (f a, f b) Source #

class Semialign f => Zip f where Source #

A unit of `zip`

.

fst <$> zip xs (full y) ≡ xs snd <$> zip (full x) ys ≡ ys

## Instances

Zip [] Source # | |

Defined in Data.Semialign.Internal | |

Zip Maybe Source # | |

Defined in Data.Semialign.Internal | |

Zip ZipList Source # | |

Defined in Data.Semialign.Internal | |

Zip Identity Source # | |

Defined in Data.Semialign.Internal | |

Zip NonEmpty Source # | |

Defined in Data.Semialign.Internal | |

Zip Tree Source # | |

Defined in Data.Semialign.Internal | |

Zip (Proxy :: Type -> Type) Source # | |

Defined in Data.Semialign.Internal | |

Zip (Tagged b) Source # | |

Defined in Data.Semialign.Internal | |

Zip ((->) e :: Type -> Type) Source # | |

Defined in Data.Semialign.Internal | |

(Zip f, Zip g) => Zip (Product f g) Source # | |

Defined in Data.Semialign.Internal | |

(Zip f, Zip g) => Zip (Compose f g) Source # | |

Defined in Data.Semialign.Internal |

class Semialign f => Unzip f where Source #

Right inverse of `zip`

.

This class is definable for every `Functor`

. See `unzipDefault`

.

## Laws

uncurry zip (unzip xs) ≡ xs unzip (zip xs xs) ≡ (xs, xs)

Note:

unzip (zip xs ys) ≢ (xs, _) or (_, ys)

For sequence-like types this holds, but for Map-like it doesn't.

## Instances

Unzip [] Source # | |

Unzip Maybe Source # | |

Unzip ZipList Source # | |

Unzip Identity Source # | |

Unzip NonEmpty Source # | |

Unzip IntMap Source # | |

Unzip Tree Source # | |

Unzip Seq Source # | |

Unzip Vector Source # | |

(Eq k, Hashable k) => Unzip (HashMap k) Source # | |

Ord k => Unzip (Map k) Source # | |

Unzip (Proxy :: Type -> Type) Source # | |

Unzip (Tagged b) Source # | |

(Unzip f, Unzip g) => Unzip (Product f g) Source # | |

(Unzip f, Unzip g) => Unzip (Compose f g) Source # | |

unzipDefault :: Functor f => f (a, b) -> (f a, f b) Source #

# Specialized aligns

salign :: (Semialign f, Semigroup a) => f a -> f a -> f a Source #

Align two structures and combine with `<>`

.

lpadZipWith :: (Maybe a -> b -> c) -> [a] -> [b] -> [c] Source #

Left-padded `zipWith`

.

rpadZipWith :: (a -> Maybe b -> c) -> [a] -> [b] -> [c] Source #

Right-padded `zipWith`

.