semialign-optics-1.1: src/Data/Semialign/Indexed.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Zipping and aligning of indexed functors.
module Data.Semialign.Indexed (
SemialignWithIndex (..),
ZipWithIndex (..),
) where
import Prelude hiding (repeat, zip, zipWith)
import Optics.Indexed (FunctorWithIndex (imap))
import Data.Align
import Data.These
import Data.Zip
-- Instances
import Control.Applicative (ZipList)
import Data.Functor.Compose (Compose (..))
import Data.Functor.Identity (Identity)
import Data.Functor.Product (Product (..))
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import Data.IntMap (IntMap)
import Data.Map (Map)
import Data.Sequence (Seq)
import Data.Vector (Vector)
import qualified Data.HashMap.Lazy as HM
import qualified Data.IntMap as IntMap
import qualified Data.Map as Map
import qualified Data.Vector as V
-- | Indexed version of 'Semialign'.
class (FunctorWithIndex i f, Semialign f) => SemialignWithIndex i f | f -> i where
-- | Analogous to 'alignWith', but also provides an index.
ialignWith :: (i -> These a b -> c) -> f a -> f b -> f c
ialignWith f a b = imap f (align a b)
-- | Indexed version of 'Zip'
class (SemialignWithIndex i f, Zip f) => ZipWithIndex i f | f -> i where
-- | Analogous to 'zipWith', but also provides an index.
izipWith :: (i -> a -> b -> c) -> f a -> f b -> f c
izipWith f a b = imap (uncurry . f) (zip a b)
-------------------------------------------------------------------------------
-- base
-------------------------------------------------------------------------------
instance SemialignWithIndex () Maybe
instance ZipWithIndex () Maybe
instance SemialignWithIndex Int []
instance ZipWithIndex Int []
instance SemialignWithIndex Int ZipList
instance ZipWithIndex Int ZipList
-------------------------------------------------------------------------------
-- transformers
-------------------------------------------------------------------------------
instance SemialignWithIndex () Identity
instance ZipWithIndex () Identity
instance (SemialignWithIndex i f, SemialignWithIndex j g) => SemialignWithIndex (Either i j) (Product f g) where
ialignWith f (Pair fa ga) (Pair fb gb) = Pair fc gc where
fc = ialignWith (f . Left) fa fb
gc = ialignWith (f . Right) ga gb
instance (ZipWithIndex i f, ZipWithIndex j g) => ZipWithIndex (Either i j) (Product f g) where
izipWith f (Pair fa ga) (Pair fb gb) = Pair fc gc where
fc = izipWith (f . Left) fa fb
gc = izipWith (f . Right) ga gb
instance (SemialignWithIndex i f, SemialignWithIndex j g) => SemialignWithIndex (i, j) (Compose f g) where
ialignWith f (Compose fga) (Compose fgb) = Compose $ ialignWith g fga fgb where
g i (This ga) = imap (\j -> f (i, j) . This) ga
g i (That gb) = imap (\j -> f (i, j) . That) gb
g i (These ga gb) = ialignWith (\j -> f (i, j)) ga gb
instance (ZipWithIndex i f, ZipWithIndex j g) => ZipWithIndex (i, j) (Compose f g) where
izipWith f (Compose fga) (Compose fgb) = Compose fgc where
fgc = izipWith (\i -> izipWith (\j -> f (i, j))) fga fgb
-------------------------------------------------------------------------------
-- containers
-------------------------------------------------------------------------------
instance SemialignWithIndex Int Seq
instance ZipWithIndex Int Seq
instance SemialignWithIndex Int IntMap
instance ZipWithIndex Int IntMap where
izipWith = IntMap.intersectionWithKey
instance Ord k => SemialignWithIndex k (Map k) where
instance Ord k => ZipWithIndex k (Map k) where
izipWith = Map.intersectionWithKey
-------------------------------------------------------------------------------
-- unordered-containers
-------------------------------------------------------------------------------
instance (Eq k, Hashable k) => SemialignWithIndex k (HashMap k) where
instance (Eq k, Hashable k) => ZipWithIndex k (HashMap k) where
izipWith = HM.intersectionWithKey
-------------------------------------------------------------------------------
-- vector
-------------------------------------------------------------------------------
instance SemialignWithIndex Int Vector where
instance ZipWithIndex Int Vector where
izipWith = V.izipWith