id-0.0.6: src/Data/BiId.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- |
-- @BiId p s t a b@ — a newtype around @p (s a) (t b)@, with optics and instances
-- for switching the type constructors @p@, @s@, and @t@.
module Data.BiId
( -- * BiId data type
BiId (..),
-- * Optics
__Wrapped,
identityBifunctor,
identityProfunctor,
identityProfunctorBifunctor,
identityBifunctorProfunctor,
identityRightBifunctor,
identityRightProfunctor,
identityRightProfunctorBifunctor,
identityRightBifunctorProfunctor,
identityLeftBifunctor,
identityLeftProfunctor,
identityLeftProfunctorBifunctor,
identityLeftBifunctorProfunctor,
-- * Type aliases
BiIdIdentity,
BiIdIdentityLeft,
BiIdIdentityRight,
Product,
Coproduct,
Exponential,
)
where
import Control.Applicative (Alternative (empty, (<|>)))
import Control.Comonad (Comonad (..))
import Control.Lens
( FoldableWithIndex (..),
FunctorWithIndex (..),
Iso,
Rewrapped,
TraversableWithIndex (..),
Wrapped (..),
iso,
)
import Control.Monad (MonadPlus (..), join)
import Control.Monad.Cont (MonadCont (..))
import Control.Monad.Error.Class (MonadError (..))
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.RWS.Class (MonadRWS)
import Control.Monad.Reader.Class (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Writer (MonadWriter (..))
import Control.Monad.Zip (MonadZip (..))
import Control.Selective (Selective (..))
import Data.Biapplicative (Biapplicative (..))
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
import Data.Bitraversable (Bitraversable (..))
import Data.Data (Data)
import Data.Distributive (Distributive (..))
import Data.Functor.Alt (Alt ((<!>)))
import Data.Functor.Apply (Apply ((<.>), liftF2))
import Data.Functor.Bind (Bind ((>>-)))
import Data.Functor.Classes
( Eq1 (..),
Eq2 (..),
Ord1 (..),
Ord2 (..),
Show1 (..),
Show2 (..),
)
import Data.Functor.Contravariant (Contravariant (..))
import Data.Functor.Contravariant.Divisible (Decidable (..), Divisible (..))
import Data.Functor.Extend (Extend (..))
import Data.Functor.Identity
import Data.Functor.Plus (Plus (..))
import Data.Profunctor (Profunctor (..))
import Data.Profunctor.Choice (Choice (..), Cochoice (..))
import Data.Profunctor.Closed (Closed (..))
import Data.Profunctor.Strong (Costrong (..), Strong (..))
import Data.Semigroup.Bifoldable (Bifoldable1 (..))
import Data.Semigroup.Bitraversable (Bitraversable1 (..))
import Data.Semigroup.Foldable (Foldable1 (..))
import Data.Semigroup.Traversable (Traversable1 (..))
import GHC.Generics (Generic, Generic1)
-- $setup
-- >>> import Control.Lens (view, over, from)
-- >>> import Data.Functor.Identity (Identity(..), runIdentity)
-- >>> import Data.Semigroup (Sum(..))
-- >>> import Data.Tagged (Tagged(..))
-- |
-- >>> BiId ([1,2,3], Identity True)
-- BiId ([1,2,3],Identity True)
--
-- >>> BiId ([1,2,3], Identity True) == BiId ([1,2,3], Identity True)
-- True
--
-- >>> BiId ([1,2,3], Identity True) == BiId ([4,5], Identity False)
-- False
--
-- >>> compare (BiId ([1], Identity True)) (BiId ([2], Identity False))
-- LT
newtype BiId p s t a b = BiId (p (s a) (t b))
deriving stock (Eq, Ord, Show, Data, Generic, Generic1)
-- |
-- >>> BiId ([1,2], [True, False]) :: Product [] [] Int Bool
-- BiId ([1,2],[True,False])
type Product s t a b = BiId (,) s t a b
-- |
-- >>> BiId (Left [1,2]) :: Coproduct [] [] Int Bool
-- BiId (Left [1,2])
type Coproduct s t a b = BiId Either s t a b
-- |
-- >>> (\(BiId f) -> f [1,2,3]) (BiId (fmap (+1)) :: Exponential [] [] Int Int)
-- [2,3,4]
type Exponential s t a b = BiId (->) s t a b
type BiIdIdentity p a b = BiId p Identity Identity a b
type BiIdIdentityLeft p t a b = BiId p Identity t a b
type BiIdIdentityRight p s a b = BiId p s Identity a b
-- |
-- >>> view identityBifunctor (BiId (Identity 3, Identity True) :: BiIdIdentity (,) Int Bool)
-- (3,True)
--
-- >>> view (from identityBifunctor) (3, True) :: BiIdIdentity (,) Int Bool
-- BiId (Identity 3,Identity True)
identityBifunctor ::
(Bifunctor p, Bifunctor p') =>
Iso
(BiIdIdentity p a b)
(BiIdIdentity p' a' b')
(p a b)
(p' a' b')
identityBifunctor =
iso
(\(BiId x) -> bimap runIdentity runIdentity x)
(BiId . bimap Identity Identity)
{-# INLINE identityBifunctor #-}
{-# SPECIALIZE identityBifunctor :: Iso (BiIdIdentity (,) a b) (BiIdIdentity (,) a' b') ((,) a b) ((,) a' b') #-}
{-# SPECIALIZE identityBifunctor :: Iso (BiIdIdentity Either a b) (BiIdIdentity Either a' b') (Either a b) (Either a' b') #-}
{-# SPECIALIZE identityBifunctor :: Iso (BiIdIdentity (,) a b) (BiIdIdentity Either a' b') ((,) a b) (Either a' b') #-}
{-# SPECIALIZE identityBifunctor :: Iso (BiIdIdentity Either a b) (BiIdIdentity (,) a' b') (Either a b) ((,) a' b') #-}
-- |
-- >>> view identityProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentity Tagged Int Bool)
-- Tagged True
--
-- >>> view (from identityProfunctor) (Tagged True) :: BiIdIdentity Tagged Int Bool
-- BiId (Tagged (Identity True))
identityProfunctor ::
(Profunctor p, Profunctor p') =>
Iso
(BiIdIdentity p a b)
(BiIdIdentity p' a' b')
(p a b)
(p' a' b')
identityProfunctor =
iso
(\(BiId x) -> dimap Identity runIdentity x)
(BiId . dimap runIdentity Identity)
{-# INLINE identityProfunctor #-}
{-# SPECIALIZE identityProfunctor :: Iso (BiIdIdentity (->) a b) (BiIdIdentity (->) a' b') ((->) a b) ((->) a' b') #-}
-- |
-- >>> view identityProfunctorBifunctor (BiId (Tagged (Identity True)) :: BiIdIdentity Tagged Int Bool) :: Tagged Int Bool
-- Tagged True
identityProfunctorBifunctor ::
(Profunctor p, Bifunctor p') =>
Iso
(BiIdIdentity p a b)
(BiIdIdentity p' a' b')
(p a b)
(p' a' b')
identityProfunctorBifunctor =
iso
(\(BiId x) -> dimap Identity runIdentity x)
(BiId . bimap Identity Identity)
{-# INLINE identityProfunctorBifunctor #-}
{-# SPECIALIZE identityProfunctorBifunctor :: Iso (BiIdIdentity (->) a b) (BiIdIdentity (,) a' b') ((->) a b) ((,) a' b') #-}
{-# SPECIALIZE identityProfunctorBifunctor :: Iso (BiIdIdentity (->) a b) (BiIdIdentity Either a' b') ((->) a b) (Either a' b') #-}
-- |
-- >>> view identityBifunctorProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentity Tagged Int Bool) :: Tagged Int Bool
-- Tagged True
identityBifunctorProfunctor ::
(Bifunctor p, Profunctor p') =>
Iso
(BiIdIdentity p a b)
(BiIdIdentity p' a' b')
(p a b)
(p' a' b')
identityBifunctorProfunctor =
iso
(\(BiId x) -> bimap runIdentity runIdentity x)
(BiId . dimap runIdentity Identity)
{-# INLINE identityBifunctorProfunctor #-}
{-# SPECIALIZE identityBifunctorProfunctor :: Iso (BiIdIdentity (,) a b) (BiIdIdentity (->) a' b') ((,) a b) ((->) a' b') #-}
{-# SPECIALIZE identityBifunctorProfunctor :: Iso (BiIdIdentity Either a b) (BiIdIdentity (->) a' b') (Either a b) ((->) a' b') #-}
-- |
-- >>> view identityRightProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentityRight Tagged [] Int Bool)
-- Tagged True
--
-- >>> view (from identityRightProfunctor) (Tagged True) :: BiIdIdentityRight Tagged [] Int Bool
-- BiId (Tagged (Identity True))
identityRightProfunctor ::
(Profunctor p, Profunctor p') =>
Iso
(BiIdIdentityRight p s a b)
(BiIdIdentityRight p' s' a' b')
(p (s a) b)
(p' (s' a') b')
identityRightProfunctor =
iso
(\(BiId x) -> rmap runIdentity x)
(BiId . rmap Identity)
{-# INLINE identityRightProfunctor #-}
-- |
-- >>> view identityRightProfunctorBifunctor (BiId (Tagged (Identity True)) :: BiIdIdentityRight Tagged [] Int Bool)
-- Tagged True
identityRightProfunctorBifunctor ::
(Profunctor p, Bifunctor p') =>
Iso
(BiIdIdentityRight p s a b)
(BiIdIdentityRight p' s' a' b')
(p (s a) b)
(p' (s' a') b')
identityRightProfunctorBifunctor =
iso
(\(BiId x) -> rmap runIdentity x)
(BiId . second Identity)
{-# INLINE identityRightProfunctorBifunctor #-}
-- |
-- >>> view identityRightBifunctorProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentityRight Tagged [] Int Bool)
-- Tagged True
identityRightBifunctorProfunctor ::
(Bifunctor p, Profunctor p') =>
Iso
(BiIdIdentityRight p s a b)
(BiIdIdentityRight p' s' a' b')
(p (s a) b)
(p' (s' a') b')
identityRightBifunctorProfunctor =
iso
(\(BiId x) -> second runIdentity x)
(BiId . rmap Identity)
{-# INLINE identityRightBifunctorProfunctor #-}
-- |
-- >>> view identityRightBifunctor (BiId ([1,2], Identity True) :: BiIdIdentityRight (,) [] Int Bool)
-- ([1,2],True)
--
-- >>> view (from identityRightBifunctor) ([1,2], True) :: BiIdIdentityRight (,) [] Int Bool
-- BiId ([1,2],Identity True)
identityRightBifunctor ::
(Bifunctor p, Bifunctor p') =>
Iso
(BiIdIdentityRight p s a b)
(BiIdIdentityRight p' s' a' b')
(p (s a) b)
(p' (s' a') b')
identityRightBifunctor =
iso
(\(BiId x) -> second runIdentity x)
(BiId . second Identity)
{-# INLINE identityRightBifunctor #-}
-- |
-- >>> view identityLeftProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentityLeft Tagged Identity Int Bool)
-- Tagged (Identity True)
--
-- >>> view (from identityLeftProfunctor) (Tagged (Identity True)) :: BiIdIdentityLeft Tagged Identity Int Bool
-- BiId (Tagged (Identity True))
identityLeftProfunctor ::
(Profunctor p, Profunctor p') =>
Iso
(BiIdIdentityLeft p t a b)
(BiIdIdentityLeft p' t' a' b')
(p a (t b))
(p' a' (t' b'))
identityLeftProfunctor =
iso
(\(BiId x) -> lmap Identity x)
(BiId . lmap runIdentity)
{-# INLINE identityLeftProfunctor #-}
-- |
-- >>> view identityLeftProfunctorBifunctor (BiId (Tagged (Identity True)) :: BiIdIdentityLeft Tagged Identity Int Bool)
-- Tagged (Identity True)
identityLeftProfunctorBifunctor ::
(Profunctor p, Bifunctor p') =>
Iso
(BiIdIdentityLeft p t a b)
(BiIdIdentityLeft p' t' a' b')
(p a (t b))
(p' a' (t' b'))
identityLeftProfunctorBifunctor =
iso
(\(BiId x) -> lmap Identity x)
(BiId . first Identity)
{-# INLINE identityLeftProfunctorBifunctor #-}
-- |
-- >>> view identityLeftBifunctorProfunctor (BiId (Tagged (Identity True)) :: BiIdIdentityLeft Tagged Identity Int Bool)
-- Tagged (Identity True)
identityLeftBifunctorProfunctor ::
(Bifunctor p, Profunctor p') =>
Iso
(BiIdIdentityLeft p t a b)
(BiIdIdentityLeft p' t' a' b')
(p a (t b))
(p' a' (t' b'))
identityLeftBifunctorProfunctor =
iso
(\(BiId x) -> first runIdentity x)
(BiId . lmap runIdentity)
{-# INLINE identityLeftBifunctorProfunctor #-}
-- |
-- >>> view identityLeftBifunctor (BiId (Identity 3, Identity True) :: BiIdIdentityLeft (,) Identity Int Bool)
-- (3,Identity True)
--
-- >>> view (from identityLeftBifunctor) (3, Identity True) :: BiIdIdentityLeft (,) Identity Int Bool
-- BiId (Identity 3,Identity True)
identityLeftBifunctor ::
(Bifunctor p, Bifunctor p') =>
Iso
(BiIdIdentityLeft p t a b)
(BiIdIdentityLeft p' t' a' b')
(p a (t b))
(p' a' (t' b'))
identityLeftBifunctor =
iso
(\(BiId x) -> first runIdentity x)
(BiId . first Identity)
{-# INLINE identityLeftBifunctor #-}
instance
(BiId p s t a b ~ x) =>
Rewrapped (BiId p s' t' a' b') x
-- |
-- >>> view _Wrapped' (BiId ([1,2,3], Identity True))
-- ([1,2,3],Identity True)
instance Wrapped (BiId p s t a b) where
type
Unwrapped (BiId p s t a b) =
p (s a) (t b)
_Wrapped' =
iso (\(BiId x) -> x) BiId
{-# INLINE _Wrapped' #-}
-- |
-- >>> view __Wrapped (BiId ([1,2,3], Identity True))
-- ([1,2,3],Identity True)
--
-- >>> view (from __Wrapped) ([1,2,3], Identity True) :: BiId (,) [] Identity Int Bool
-- BiId ([1,2,3],Identity True)
--
-- >>> over __Wrapped (\(xs, Identity b) -> (fmap (+1) xs, Identity (not b))) (BiId ([1,2,3], Identity True))
-- BiId ([2,3,4],Identity False)
__Wrapped ::
Iso
(BiId p s t a b)
(BiId p' s' t' a' b')
(p (s a) (t b))
(p' (s' a') (t' b'))
__Wrapped =
iso
(\(BiId x) -> x)
BiId
{-# INLINE __Wrapped #-}
-- |
-- >>> liftEq (==) (BiId ([1,2], Identity True)) (BiId ([1,2], Identity True))
-- True
--
-- >>> liftEq (==) (BiId ([1,2], Identity True)) (BiId ([1,2], Identity False))
-- False
instance (Eq1 (p (s a)), Eq1 t) => Eq1 (BiId p s t a) where
liftEq f (BiId x) (BiId y) =
liftEq (liftEq f) x y
{-# INLINE liftEq #-}
-- |
-- >>> liftCompare compare (BiId ([1], Identity 'a')) (BiId ([1], Identity 'b'))
-- LT
instance (Ord1 (p (s a)), Ord1 t) => Ord1 (BiId p s t a) where
liftCompare f (BiId x) (BiId y) =
liftCompare (liftCompare f) x y
{-# INLINE liftCompare #-}
-- |
-- >>> liftShowsPrec showsPrec showList 0 (BiId ([1,2], Identity True)) ""
-- "BiId ([1,2],Identity True)"
instance (Show1 (p (s a)), Show1 t) => Show1 (BiId p s t a) where
liftShowsPrec sp l d (BiId x) =
showParen (d > 10) $ showString "BiId " . liftShowsPrec (liftShowsPrec sp l) (liftShowList sp l) 11 x
{-# INLINE liftShowsPrec #-}
-- |
-- >>> liftEq2 (==) (==) (BiId ([1,2], Identity True)) (BiId ([1,2], Identity True))
-- True
--
-- >>> liftEq2 (==) (==) (BiId ([1,2], Identity True)) (BiId ([3,4], Identity True))
-- False
instance (Eq2 p, Eq1 s, Eq1 t) => Eq2 (BiId p s t) where
liftEq2 f g (BiId x) (BiId y) =
liftEq2 (liftEq f) (liftEq g) x y
{-# INLINE liftEq2 #-}
-- |
-- >>> liftCompare2 compare compare (BiId ([1], Identity 'a')) (BiId ([2], Identity 'a'))
-- LT
instance (Ord2 p, Ord1 s, Ord1 t) => Ord2 (BiId p s t) where
liftCompare2 f g (BiId x) (BiId y) =
liftCompare2 (liftCompare f) (liftCompare g) x y
{-# INLINE liftCompare2 #-}
-- |
-- >>> liftShowsPrec2 showsPrec showList showsPrec showList 0 (BiId ([1,2], Identity True)) ""
-- "BiId ([1,2],Identity True)"
instance (Show2 p, Show1 s, Show1 t) => Show2 (BiId p s t) where
liftShowsPrec2 spa la spb lb d (BiId x) =
showParen (d > 10) $ showString "BiId " . liftShowsPrec2 (liftShowsPrec spa la) (liftShowList spa la) (liftShowsPrec spb lb) (liftShowList spb lb) 11 x
{-# INLINE liftShowsPrec2 #-}
-- |
-- >>> dimap (+1) (*2) (BiId (Tagged (Identity 3))) :: BiId Tagged [] Identity Int Int
-- BiId (Tagged (Identity 6))
instance (Profunctor p, Functor s, Functor t) => Profunctor (BiId p s t) where
dimap f g (BiId x) =
BiId (dimap (fmap f) (fmap g) x)
{-# INLINE dimap #-}
lmap f (BiId x) =
BiId (lmap (fmap f) x)
{-# INLINE lmap #-}
rmap f (BiId x) =
BiId (rmap (fmap f) x)
{-# INLINE rmap #-}
-- |
-- >>> let f = first' (BiId id :: BiId (->) Identity Identity Int Int)
-- >>> (\(BiId g) -> g) f (Identity (3, 'x'))
-- Identity (3,'x')
instance (Strong p, Comonad s, Functor t) => Strong (BiId p s t) where
first' (BiId x) =
BiId
( dimap
(\sac -> (fmap fst sac, snd (extract sac)))
(\(tb, c) -> fmap (, c) tb)
(first' x)
)
{-# INLINE first' #-}
second' (BiId x) =
BiId
( dimap
(\sca -> (fst (extract sca), fmap snd sca))
(\(c, tb) -> fmap (c,) tb)
(second' x)
)
{-# INLINE second' #-}
-- |
-- >>> let f = left' (BiId id :: BiId (->) Identity Identity Int Int)
-- >>> (\(BiId g) -> g) f (Identity (Left 3))
-- Identity (Left 3)
instance (Choice p, Traversable s, Applicative t) => Choice (BiId p s t) where
left' (BiId x) =
BiId
( dimap
(either Right Left . traverse (either Right Left))
(either (fmap Left) (pure . Right))
(left' x)
)
{-# INLINE left' #-}
right' (BiId x) =
BiId
( dimap
(either Left Right . traverse (either Left Right))
(either (pure . Left) (fmap Right))
(right' x)
)
{-# INLINE right' #-}
-- |
-- >>> let BiId f = closed (BiId id :: BiId (->) Identity Identity Int Int)
-- >>> runIdentity (f (Identity (const 7))) 'x'
-- 7
instance (Closed p, Distributive s, Distributive t) => Closed (BiId p s t) where
closed (BiId x) =
BiId (dimap distribute distribute (closed x))
{-# INLINE closed #-}
-- |
-- >>> bimap (+1) not (BiId ([1,2,3], Identity True))
-- BiId ([2,3,4],Identity False)
instance (Bifunctor p, Functor s, Functor t) => Bifunctor (BiId p s t) where
bimap f g (BiId x) =
BiId (bimap (fmap f) (fmap g) x)
{-# INLINE bimap #-}
first f (BiId x) =
BiId (first (fmap f) x)
{-# INLINE first #-}
second f (BiId x) =
BiId (second (fmap f) x)
{-# INLINE second #-}
-- |
-- >>> bifoldMap Sum Sum (BiId ([1,2,3], Identity 4))
-- Sum {getSum = 10}
instance (Bifoldable p, Foldable s, Foldable t) => Bifoldable (BiId p s t) where
bifoldMap f g (BiId x) =
bifoldMap (foldMap f) (foldMap g) x
{-# INLINE bifoldMap #-}
-- |
-- >>> bifoldMap1 Sum Sum (BiId (Identity 3, Identity 4))
-- Sum {getSum = 7}
instance (Bifoldable1 p, Foldable1 s, Foldable1 t) => Bifoldable1 (BiId p s t) where
bifoldMap1 f g (BiId x) =
bifoldMap1 (foldMap1 f) (foldMap1 g) x
{-# INLINE bifoldMap1 #-}
-- |
-- >>> bitraverse (\x -> if x > 2 then Nothing else Just (x * 10)) (\x -> Just (not x)) (BiId ([1,2], Identity True))
-- Just (BiId ([10,20],Identity False))
--
-- >>> bitraverse (\x -> if x > 2 then Nothing else Just (x * 10)) (\x -> Just (not x)) (BiId ([1,3], Identity True))
-- Nothing
instance (Bitraversable p, Traversable s, Traversable t) => Bitraversable (BiId p s t) where
bitraverse f g (BiId x) =
BiId <$> bitraverse (traverse f) (traverse g) x
{-# INLINE bitraverse #-}
-- |
-- >>> bitraverse1 Just Just (BiId (Identity 3, Identity True))
-- Just (BiId (Identity 3,Identity True))
instance (Bitraversable1 p, Traversable1 s, Traversable1 t) => Bitraversable1 (BiId p s t) where
bitraverse1 f g (BiId x) =
BiId <$> bitraverse1 (traverse1 f) (traverse1 g) x
{-# INLINE bitraverse1 #-}
-- |
-- >>> fmap (+1) (BiId ([1,2,3], Identity 4))
-- BiId ([1,2,3],Identity 5)
instance (Functor (p (s a)), Functor t) => Functor (BiId p s t a) where
fmap f (BiId x) =
BiId (fmap (fmap f) x)
{-# INLINE fmap #-}
-- |
-- >>> foldMap Sum (BiId ([1,2,3], Identity 4))
-- Sum {getSum = 4}
instance (Foldable (p (s a)), Foldable t) => Foldable (BiId p s t a) where
foldMap f (BiId x) =
foldMap (foldMap f) x
{-# INLINE foldMap #-}
-- |
-- >>> traverse (\x -> if x > 3 then Nothing else Just (x * 10)) (BiId ([1,2], Identity 3))
-- Just (BiId ([1,2],Identity 30))
--
-- >>> traverse (\x -> if x > 3 then Nothing else Just (x * 10)) (BiId ([1,2], Identity 4))
-- Nothing
instance (Traversable (p (s a)), Traversable t) => Traversable (BiId p s t a) where
traverse f (BiId x) =
BiId <$> traverse (traverse f) x
{-# INLINE traverse #-}
-- |
-- >>> (BiId ("", Identity (+1)) :: BiId (,) [] Identity Char (Int -> Int)) <.> BiId ("", Identity 10)
-- BiId ("",Identity 11)
instance (Apply (p (s a)), Apply t) => Apply (BiId p s t a) where
BiId x <.> BiId y =
BiId (liftF2 (<.>) x y)
{-# INLINE (<.>) #-}
-- |
-- >>> pure 7 :: BiId (,) [] Identity Int Int
-- BiId ([],Identity 7)
--
-- >>> (BiId ("", Identity (+1)) :: BiId (,) [] Identity Char (Int -> Int)) <*> BiId ("", Identity 10)
-- BiId ("",Identity 11)
instance (Applicative (p (s a)), Applicative t) => Applicative (BiId p s t a) where
pure b =
BiId (pure (pure b))
{-# INLINE pure #-}
BiId x <*> BiId y =
BiId (liftA2 (<*>) x y)
{-# INLINE (<*>) #-}
-- |
-- >>> BiId ("hello", Identity 3) >>- (\b -> BiId ("!", Identity (b + 1)))
-- BiId ("hello!",Identity 4)
instance (Apply (p (s a)), Monad (p (s a)), Apply t, Traversable t, Monad t) => Bind (BiId p s t a) where
BiId x >>- f =
BiId (x >>= \tb -> fmap join (mapM (\b -> let BiId y = f b in y) tb))
{-# INLINE (>>-) #-}
-- |
-- >>> BiId ("hello", Identity 3) >>= (\b -> BiId ("!", Identity (b + 1)))
-- BiId ("hello!",Identity 4)
instance (Monad (p (s a)), Traversable t, Monad t) => Monad (BiId p s t a) where
BiId x >>= f =
BiId (x >>= \tb -> fmap join (mapM (\b -> let BiId y = f b in y) tb))
{-# INLINE (>>=) #-}
-- |
-- >>> bipure 'a' True :: BiId (,) Identity Identity Char Bool
-- BiId (Identity 'a',Identity True)
instance (Biapplicative p, Applicative s, Applicative t) => Biapplicative (BiId p s t) where
bipure a b =
BiId (bipure (pure a) (pure b))
{-# INLINE bipure #-}
BiId x <<*>> BiId y =
BiId (biliftA2 (liftA2 ($)) (liftA2 ($)) x y)
{-# INLINE (<<*>>) #-}
-- |
-- >>> import Control.Lens (imap)
-- >>> imap (\(i, j) x -> (i, j, x)) (BiId (["hello", "world"], Identity 7))
-- BiId (["hello","world"],Identity (["hello","world"],(),7))
instance (FunctorWithIndex i (p (s a)), FunctorWithIndex j t) => FunctorWithIndex (i, j) (BiId p s t a) where
imap f (BiId x) =
BiId (imap (\i -> imap (\j -> f (i, j))) x)
{-# INLINE imap #-}
-- |
-- >>> import Control.Lens (ifoldMap)
-- >>> ifoldMap (\(i, _) x -> [(i, x)]) (BiId (["hello", "world"], Identity 7))
-- [(["hello","world"],7)]
instance (FoldableWithIndex i (p (s a)), Foldable (p (s a)), FoldableWithIndex j t, Foldable t) => FoldableWithIndex (i, j) (BiId p s t a) where
ifoldMap f (BiId x) =
ifoldMap (\i -> ifoldMap (\j -> f (i, j))) x
{-# INLINE ifoldMap #-}
-- |
-- >>> import Control.Lens (itraverse)
-- >>> itraverse (\(_, _) x -> Just (x + 1)) (BiId (["hello"], Identity 7))
-- Just (BiId (["hello"],Identity 8))
instance (TraversableWithIndex i (p (s a)), Traversable (p (s a)), FoldableWithIndex i (p (s a)), Foldable (p (s a)), TraversableWithIndex j t, Traversable t, FoldableWithIndex j t, Foldable t, Functor (p (s a)), Functor t) => TraversableWithIndex (i, j) (BiId p s t a) where
itraverse f (BiId x) =
BiId <$> itraverse (\i -> itraverse (\j -> f (i, j))) x
{-# INLINE itraverse #-}
-- |
-- >>> select (BiId ("", Identity (Right 7))) (BiId ("x", Identity (+1)))
-- BiId ("x",Identity 7)
--
-- >>> select (BiId ("", Identity (Left 3))) (BiId ("x", Identity (+1)))
-- BiId ("x",Identity 4)
instance (Applicative (p (s a)), Selective t) => Selective (BiId p s t a) where
select (BiId x) (BiId y) =
BiId (liftA2 select x y)
{-# INLINE select #-}
instance (Alt (p (s a)), Functor (p (s a)), Functor t) => Alt (BiId p s t a) where
BiId x <!> BiId y =
BiId (x <!> y)
{-# INLINE (<!>) #-}
instance (Alternative (p (s a)), Applicative t) => Alternative (BiId p s t a) where
BiId x <|> BiId y =
BiId (x <|> y)
{-# INLINE (<|>) #-}
empty =
BiId empty
{-# INLINE empty #-}
instance (Plus (p (s a)), Functor (p (s a)), Functor t) => Plus (BiId p s t a) where
zero =
BiId zero
{-# INLINE zero #-}
-- |
-- >>> import Data.Functor.Contravariant (Predicate(..), getPredicate)
-- >>> getPredicate ((\(BiId (Tagged x)) -> x) (contramap length (BiId (Tagged (Predicate (> 3))) :: BiId Tagged [] Predicate Int Int))) "hello"
-- True
instance (Functor (p (s a)), Contravariant t) => Contravariant (BiId p s t a) where
contramap f (BiId x) =
BiId (fmap (contramap f) x)
{-# INLINE contramap #-}
-- |
-- >>> import Data.Functor.Contravariant (Predicate(..), getPredicate)
-- >>> import Data.Functor.Contravariant.Divisible (divided)
-- >>> let BiId (Tagged p) = divided (BiId (Tagged (Predicate even))) (BiId (Tagged (Predicate (> 0)))) :: BiId Tagged [] Predicate Int (Int, Int) in getPredicate p (4, 1)
-- True
instance (Applicative (p (s a)), Divisible t) => Divisible (BiId p s t a) where
divide f (BiId x) (BiId y) =
BiId (liftA2 (divide f) x y)
{-# INLINE divide #-}
conquer =
BiId (pure conquer)
{-# INLINE conquer #-}
-- |
-- >>> import Data.Functor.Contravariant (Predicate(..), getPredicate)
-- >>> import Data.Functor.Contravariant.Divisible (chosen)
-- >>> let BiId (Tagged p) = chosen (BiId (Tagged (Predicate even))) (BiId (Tagged (Predicate (> 0)))) :: BiId Tagged [] Predicate Int (Either Int Int) in getPredicate p (Left 4)
-- True
instance (Applicative (p (s a)), Decidable t) => Decidable (BiId p s t a) where
choose f (BiId x) (BiId y) =
BiId (liftA2 (choose f) x y)
{-# INLINE choose #-}
lose f =
BiId (pure (lose f))
{-# INLINE lose #-}
-- |
-- >>> let f = unfirst (BiId (Tagged (Identity (True, 'x')))) :: BiId Tagged Identity Identity Int Bool
-- >>> (\(BiId (Tagged x)) -> x) f
-- Identity True
instance (Costrong p, Functor s, Comonad t) => Costrong (BiId p s t) where
unfirst (BiId x) =
BiId
( unfirst
( dimap
(\(sa, d) -> fmap (, d) sa)
(\tbd -> (fmap fst tbd, snd (extract tbd)))
x
)
)
{-# INLINE unfirst #-}
unsecond (BiId x) =
BiId
( unsecond
( dimap
(\(d, sa) -> fmap (d,) sa)
(\tdb -> (fst (extract tdb), fmap snd tdb))
x
)
)
{-# INLINE unsecond #-}
-- |
-- >>> let BiId f = unleft (BiId id :: BiId (->) Identity Identity (Either Int Char) (Either Int Char))
-- >>> f (Identity 7)
-- Identity 7
instance (Cochoice p, Applicative s, Traversable t) => Cochoice (BiId p s t) where
unleft (BiId x) =
BiId
( unleft
( dimap
(either (fmap Left) (pure . Right))
(either Right Left . traverse (either Right Left))
x
)
)
{-# INLINE unleft #-}
unright (BiId x) =
BiId
( unright
( dimap
(either (pure . Left) (fmap Right))
(either Left Right . traverse (either Left Right))
x
)
)
{-# INLINE unright #-}
-- |
-- >>> BiId ([1,2], [3,4]) <> BiId ([5], [6]) :: BiId (,) [] [] Int Int
-- BiId ([1,2,5],[3,4,6])
deriving newtype instance (Semigroup (p (s a) (t b))) => Semigroup (BiId p s t a b)
-- |
-- >>> mempty :: BiId (,) [] [] Int Int
-- BiId ([],[])
deriving newtype instance (Monoid (p (s a) (t b))) => Monoid (BiId p s t a b)
-- |
-- >>> duplicated (BiId (Identity 7, Identity True))
-- BiId (Identity 7,Identity (BiId (Identity 7,Identity True)))
instance (Comonad (p (s a)), Comonad t) => Extend (BiId p s t a) where
duplicated (BiId x) =
BiId (extend (\px -> extend (\tb -> BiId (fmap (const tb) px)) (extract px)) x)
{-# INLINE duplicated #-}
-- |
-- >>> extract (BiId (Identity 7, Identity True))
-- True
instance (Comonad (p (s a)), Comonad t) => Comonad (BiId p s t a) where
extract (BiId x) =
extract (extract x)
{-# INLINE extract #-}
duplicate (BiId x) =
BiId (extend (\px -> extend (\tb -> BiId (fmap (const tb) px)) (extract px)) x)
{-# INLINE duplicate #-}
-- |
-- >>> foldMap1 Sum (BiId (Identity "hello", Identity 7))
-- Sum {getSum = 7}
instance (Foldable1 (p (s a)), Foldable1 t) => Foldable1 (BiId p s t a) where
foldMap1 f (BiId x) =
foldMap1 (foldMap1 f) x
{-# INLINE foldMap1 #-}
-- |
-- >>> traverse1 Just (BiId (Identity "hello", Identity 7))
-- Just (BiId (Identity "hello",Identity 7))
instance (Traversable1 (p (s a)), Traversable1 t) => Traversable1 (BiId p s t a) where
traverse1 f (BiId x) =
BiId <$> traverse1 (traverse1 f) x
{-# INLINE traverse1 #-}
instance (MonadPlus (p (s a)), Monad t, Traversable t) => MonadPlus (BiId p s t a)
-- |
-- >>> distribute [BiId (Tagged (Identity 1)), BiId (Tagged (Identity 2))] :: BiId Tagged [] Identity Int [Int]
-- BiId (Tagged (Identity [1,2]))
instance (Distributive (p (s a)), Distributive t) => Distributive (BiId p s t a) where
distribute x =
BiId (fmap distribute (distribute (fmap (\(BiId y) -> y) x)))
{-# INLINE distribute #-}
collect f x =
distribute (fmap f x)
{-# INLINE collect #-}
instance (MonadZip (p (s a)), MonadZip t, Traversable t, Monad t, Monad (p (s a))) => MonadZip (BiId p s t a) where
mzipWith f (BiId x) (BiId y) =
BiId (mzipWith (mzipWith f) x y)
{-# INLINE mzipWith #-}
instance (MonadFail (p (s a)), Traversable t, Monad t) => MonadFail (BiId p s t a) where
fail s =
BiId (fail s)
{-# INLINE fail #-}
instance (MonadIO (p (s a)), Applicative t, Traversable t, Monad t) => MonadIO (BiId p s t a) where
liftIO =
BiId . fmap pure . liftIO
{-# INLINE liftIO #-}
-- |
-- >>> import Control.Monad.Reader (runReader)
-- >>> (\(BiId f) -> f (Identity 42)) (ask :: BiId (->) Identity Identity Int (Identity Int))
-- Identity (Identity 42)
instance (MonadReader r (p (s a)), Traversable t, Monad t) => MonadReader r (BiId p s t a) where
ask =
BiId (fmap pure ask)
{-# INLINE ask #-}
local f (BiId x) =
BiId (local f x)
{-# INLINE local #-}
reader f =
BiId (fmap pure (reader f))
{-# INLINE reader #-}
instance (MonadState st (p (s a)), Traversable t, Monad t) => MonadState st (BiId p s t a) where
get =
BiId (fmap pure get)
{-# INLINE get #-}
put =
BiId . fmap pure . put
{-# INLINE put #-}
state f =
BiId (fmap pure (state f))
{-# INLINE state #-}
instance (MonadWriter w (p (s a)), Comonad t, Traversable t, Monad t) => MonadWriter w (BiId p s t a) where
writer aw =
BiId (fmap pure (writer aw))
{-# INLINE writer #-}
tell =
BiId . fmap pure . tell
{-# INLINE tell #-}
listen (BiId x) =
BiId (fmap (\(tb, w) -> fmap (, w) tb) (listen x))
{-# INLINE listen #-}
pass (BiId x) =
BiId (pass (fmap (\twf -> (fmap fst twf, snd (extract twf))) x))
{-# INLINE pass #-}
instance (MonadError e (p (s a)), Traversable t, Monad t) => MonadError e (BiId p s t a) where
throwError =
BiId . fmap pure . throwError
{-# INLINE throwError #-}
catchError (BiId x) f =
BiId (catchError x (\e -> let BiId y = f e in y))
{-# INLINE catchError #-}
instance (MonadCont (p (s a)), Traversable t, Monad t) => MonadCont (BiId p s t a) where
callCC f =
BiId (callCC (\k -> let BiId x = f (BiId . k . pure) in x))
{-# INLINE callCC #-}
instance (MonadRWS r w st (p (s a)), Comonad t, Traversable t, Monad t) => MonadRWS r w st (BiId p s t a)