distributors-0.4.0.0: src/Data/Traversable/Homogeneous.hs
{-|
Module : Data.Traversable.Homogeneous
Description : homogeneous
Copyright : (C) 2026 - Eitan Chatav
License : BSD-style (see the file LICENSE)
Maintainer : Eitan Chatav <eitan.chatav@gmail.com>
Stability : provisional
Portability : non-portable
-}
module Data.Traversable.Homogeneous
( -- * Homogeneous
Homogeneous (..)
) where
import Control.Applicative
import Control.Lens hiding (chosen)
import Control.Lens.PartialIso
import Data.Complex
import Data.Functor.Compose
import qualified Data.Functor.Product as Functor
import qualified Data.Functor.Sum as Functor
import qualified Data.Monoid as Monoid
import Data.Profunctor.Monoidal
import Data.Proxy
import Data.Sequence (Seq)
import Data.Tagged
import Data.Tree (Tree (..))
import Data.Vector (Vector)
import Data.Void
import GHC.Generics
import Data.Profunctor.Distributor
{- | A class of `Homogeneous`
countable sums of countable products.
-}
class Traversable t => Homogeneous t where
{- | Sequences actions `homogeneously`.
prop> homogeneously @Maybe = optionalP
prop> homogeneously @[] = manyP
Any `Traversable` & `Data.Distributive.Distributive` countable product
can be given a default implementation for the `homogeneously` method
with `ditraverse`.
prop> homogeneously = ditraverse
And any user-defined homogeneous algebraic datatype has
a default instance for `Homogeneous`, by deriving `Generic1`.
-}
homogeneously :: Distributor p => p a b -> p (t a) (t b)
default homogeneously
:: (Generic1 t, Homogeneous (Rep1 t), Distributor p)
=> p a b -> p (t a) (t b)
homogeneously = dimap from1 to1 . homogeneously
instance Homogeneous Par1 where
homogeneously = dimap unPar1 Par1
instance Homogeneous Identity where
homogeneously = dimap runIdentity Identity
instance Homogeneous Monoid.Dual where
homogeneously = dimap Monoid.getDual Monoid.Dual
instance Homogeneous Monoid.Product where
homogeneously = dimap Monoid.getProduct Monoid.Product
instance Homogeneous Monoid.Sum where
homogeneously = dimap Monoid.getSum Monoid.Sum
instance Homogeneous (Tagged s) where
homogeneously = dimap unTagged Tagged
instance Homogeneous U1 where
homogeneously _ = pure U1
instance Homogeneous (K1 i ()) where
homogeneously _ = pure (K1 ())
instance Homogeneous (Const ()) where
homogeneously _ = pure (Const ())
instance Homogeneous Proxy where
homogeneously _ = pure Proxy
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (s :.: t) where
homogeneously
= dimap unComp1 Comp1
. homogeneously . homogeneously
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (Compose s t) where
homogeneously
= dimap getCompose Compose
. homogeneously . homogeneously
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (s :*: t) where
homogeneously p = dimap2
(\(s :*: _) -> s)
(\(_ :*: t) -> t)
(:*:)
(homogeneously p)
(homogeneously p)
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (Functor.Product s t) where
homogeneously p = dimap2
(\(Functor.Pair s _) -> s)
(\(Functor.Pair _ t) -> t)
Functor.Pair
(homogeneously p)
(homogeneously p)
instance Homogeneous V1 where
homogeneously _ = dimap (\case) (\case) zeroP
instance Homogeneous (K1 i Void) where
homogeneously _ = dimap unK1 K1 zeroP
instance Homogeneous (Const Void) where
homogeneously _ = dimap getConst Const zeroP
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (s :+: t) where
homogeneously p = dialt
(\case {L1 s -> Left s; R1 t -> Right t})
L1
R1
(homogeneously p)
(homogeneously p)
instance (Homogeneous s, Homogeneous t)
=> Homogeneous (Functor.Sum s t) where
homogeneously p = dialt
(\case {Functor.InL s -> Left s; Functor.InR t -> Right t})
Functor.InL
Functor.InR
(homogeneously p)
(homogeneously p)
instance Homogeneous t
=> Homogeneous (M1 i c t) where
homogeneously = dimap unM1 M1 . homogeneously
instance Homogeneous f => Homogeneous (Rec1 f) where
homogeneously = dimap unRec1 Rec1 . homogeneously
instance Homogeneous Maybe where
homogeneously = optionalP
instance Homogeneous [] where
homogeneously = manyP
instance Homogeneous Vector where
homogeneously p = eotList >~ p >*< homogeneously p >+< oneP
instance Homogeneous Seq where
homogeneously p = eotList >~ p >*< homogeneously p >+< oneP
instance Homogeneous Complex where
homogeneously p = dimap2 realPart imagPart (:+) p p
instance Homogeneous Tree where
homogeneously p = dimap2 rootLabel subForest Node p (manyP (homogeneously p))