packages feed

subcategories (empty) → 0.1.0.0

raw patch · 23 files changed

+4099/−0 lines, 23 filesdep +QuickCheckdep +basedep +bytestringsetup-changed

Dependencies added: QuickCheck, base, bytestring, containers, data-default, foldl, hashable, inspection-testing, mono-traversable, pointed, primitive, reflection, semialign, subcategories, tasty, tasty-expected-failure, tasty-hunit, tasty-quickcheck, template-haskell, text, these, unordered-containers, vector, vector-algorithms, vector-builder

Files

+ ChangeLog.md view
@@ -0,0 +1,4 @@+# Changelog for subcategories++## 0.1.0.0+Initial Release
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Hiromi ISHII (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Hiromi ISHII nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,32 @@+# The `subcategories` package++This package provides variants of functor-like structures,+with domain types are constrained.+In particular, this package provides an abstraction for functorial+containers, which can be expressed as a functor from a *full-subcategory*+of **Hask** to **Hask** itself [^1].++For example:++- We can treat `Set` as if it is a `Fuctor`, `Foldable`, `Applicative`,+  with their domain restricted to full-subcategory **Ord** of `Ord` instances+  of **Hask**.+- For `MonoFoldable` or `MonoTraversable` types (from `mono-traversable` package),+  we provide `WrapMono` wrapper with zero-cost coercion. Such `mono`s can be+  regarded as a functorial structure from the full subcategory consisting of just a single object,+  say `Element mono`.++[^1]: Strictly speaking, `CFoldable`, a constrained counterpart of `Foldable`, doesn't require a functoriality as with the original `Foldable`.++## Optimisation+This library is designed to keep the abstraction runtime overhead as minimum as possible.++Some notes:++- If a constrained term such as `cmap` or `czipWith` has concrete type, it must have exactly the same representation as the corresponding operation modulo (zero-cost) coercion.+  * The same still holds if the set of required constraints coincides.+  * Although the constructor of `WrapMono mono a` is hidden, its just a `newtype`-wrapper around `mono`;+    hence, constrained operators must have the same representations as the corresponding combinators+    in `mono-traversable` package.+- OTOH, for a polymorphic term, like `cmap :: (Ord a, Ord b) => (a -> b) Set a -> Set b`+  and `Set.map`, they can have different representations; indeed, `Set.map` doesn't require `a` to be `Ord`-instance and therefore the implementation of `cmap` discards the dictionary for `Ord a` to call `Set.map`.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Control/Subcategory.hs view
@@ -0,0 +1,17 @@+module Control.Subcategory+  ( module Control.Subcategory.Applicative+  , module Control.Subcategory.Alternative+  , module Control.Subcategory.Bind+  , module Control.Subcategory.Functor+  , module Control.Subcategory.Foldable+  , module Control.Subcategory.Zip+  , module Control.Subcategory.Pointed+  ) where++import Control.Subcategory.Alternative+import Control.Subcategory.Applicative+import Control.Subcategory.Bind+import Control.Subcategory.Foldable+import Control.Subcategory.Functor+import Control.Subcategory.Pointed+import Control.Subcategory.Zip
+ src/Control/Subcategory/Alternative.hs view
@@ -0,0 +1,159 @@+{-# LANGUAGE EmptyCase, ScopedTypeVariables, StandaloneDeriving #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Control.Subcategory.Alternative+  (CAlternative(..), CChoice(..), CAlt(..)) where+import Control.Subcategory.Alternative.Class+import Control.Subcategory.Applicative.Class+import Control.Subcategory.Functor+import Control.Subcategory.Pointed++import qualified Control.Applicative             as App+import           Data.Coerce                     (coerce)+import qualified Data.Functor.Compose            as SOP+import qualified Data.Functor.Product            as SOP+import           Data.Hashable                   (Hashable)+import qualified Data.HashMap.Strict             as HM+import qualified Data.HashSet                    as HS+import qualified Data.IntMap                     as IM+import           Data.List.NonEmpty              (NonEmpty)+import qualified Data.Map                        as Map+import           Data.MonoTraversable            (GrowingAppend, MonoFunctor)+import qualified Data.Primitive.Array            as A+import qualified Data.Primitive.PrimArray        as PA+import qualified Data.Primitive.SmallArray       as SA+import qualified Data.Semigroup                  as Sem+import qualified Data.Sequence                   as Seq+import qualified Data.Set                        as Set+import qualified Data.Vector                     as V+import qualified Data.Vector.Primitive           as P+import qualified Data.Vector.Storable            as S+import qualified Data.Vector.Unboxed             as U+import           Text.ParserCombinators.ReadP    (ReadP)+import           Text.ParserCombinators.ReadPrec (ReadPrec)++instance CChoice []+instance CChoice Maybe+instance CChoice V.Vector+instance CChoice U.Vector where+  (<!>) = (<>)+  {-# INLINE [1] (<!>) #-}+instance CChoice S.Vector where+  (<!>) = (<>)+  {-# INLINE [1] (<!>) #-}+instance CChoice P.Vector where+  (<!>) = (<>)+  {-# INLINE [1] (<!>) #-}+instance CChoice PA.PrimArray where+  (<!>) = (<>)+  {-# INLINE [1] (<!>) #-}+instance CChoice SA.SmallArray+instance CChoice A.Array+instance CChoice Seq.Seq+instance CChoice Sem.Option+instance CChoice NonEmpty where+  (<!>) = (Sem.<>)+  {-# INLINE (<!>) #-}+instance CChoice (Either a) where+  Left _ <!> b = b+  a      <!> _ = a+  {-# INLINE (<!>) #-}+instance CChoice IM.IntMap where+  (<!>) = IM.union+instance CChoice ReadP+instance CChoice ReadPrec+instance (CChoice f, CFunctor g) => CChoice (SOP.Compose f g) where+  SOP.Compose a <!> SOP.Compose b = SOP.Compose (a <!> b)+  {-# INLINE (<!>) #-}++instance (CChoice f, CChoice g) => CChoice (SOP.Product f g) where+  SOP.Pair a1 b1 <!> SOP.Pair a2 b2 =+    SOP.Pair (a1 <!> a2) (b1 <!> b2)+  {-# INLINE (<!>) #-}++instance CChoice HS.HashSet where+  (<!>) = HS.union+  {-# INLINE (<!>) #-}++instance CChoice Set.Set where+  (<!>) = Set.union+  {-# INLINE (<!>) #-}++instance Ord k => CChoice (Map.Map k) where+  (<!>) = Map.union+  {-# INLINE (<!>) #-}++instance+    (MonoFunctor mono, GrowingAppend mono, Semigroup mono)+  => CChoice (WrapMono mono) where+  (<!>) = (<>)+  {-# INLINE [1] (<!>) #-}++instance (Eq k, Hashable k) => CChoice (HM.HashMap k) where+  (<!>) = HM.union+  {-# INLINE (<!>) #-}++instance CAlternative IM.IntMap where+  cempty = IM.empty+  {-# INLINE cempty #-}+instance (Eq k, Hashable k) => CAlternative (HM.HashMap k) where+  cempty = HM.empty+  {-# INLINE cempty #-}+instance Ord k => CAlternative (Map.Map k) where+  cempty = Map.empty+  {-# INLINE cempty #-}+instance CAlternative HS.HashSet where+  cempty = HS.empty+  {-# INLINE cempty #-}+instance CAlternative Set.Set where+  cempty = Set.empty+  {-# INLINE cempty #-}+instance (MonoFunctor mono, Monoid mono, GrowingAppend mono)+      => CAlternative (WrapMono mono) where+  cempty = WrapMono mempty+  {-# INLINE [1] cempty #-}++instance (CAlternative f, CFunctor g) => CAlternative (SOP.Compose f g) where+  cempty = SOP.Compose cempty+  {-# INLINE cempty #-}++instance (CAlternative f, CAlternative g) => CAlternative (SOP.Product f g) where+  cempty = SOP.Pair cempty cempty+  {-# INLINE cempty #-}++instance CAlternative []+instance CAlternative Maybe+instance CAlternative Seq.Seq+instance CAlternative Sem.Option+instance CAlternative ReadP+instance CAlternative V.Vector+instance CAlternative U.Vector where+  cempty = U.empty+  {-# INLINE [1] cempty #-}+instance CAlternative S.Vector where+  cempty = S.empty+  {-# INLINE [1] cempty #-}+instance CAlternative P.Vector where+  cempty = P.empty+  {-# INLINE [1] cempty #-}+instance CAlternative PA.PrimArray where+  cempty = PA.primArrayFromListN 0 []+  {-# INLINE [1] cempty #-}+instance CAlternative SA.SmallArray+instance CAlternative A.Array+instance CAlternative ReadPrec++newtype CAlt f a = CAlt { runAlt :: f a }+  deriving newtype (Functor, Constrained, Applicative, App.Alternative)+deriving newtype instance CFunctor f => CFunctor (CAlt f)+deriving newtype instance CChoice f => CChoice (CAlt f)+deriving newtype instance CAlternative f => CAlternative (CAlt f)+deriving newtype instance CApplicative f => CApplicative (CAlt f)+deriving newtype instance CPointed f => CPointed (CAlt f)+++instance (Dom f a, CChoice f) => Sem.Semigroup (CAlt f a) where+  (<>) = coerce @(f a -> f a -> f a) (<!>)++instance (Dom f a, CAlternative f) => Monoid (CAlt f a) where+  mempty = coerce @(f a) cempty+  mappend = coerce @(f a -> f a -> f a) (<!>)
+ src/Control/Subcategory/Alternative/Class.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE EmptyCase, UndecidableSuperClasses #-}+module Control.Subcategory.Alternative.Class+  (CChoice(..), CAlternative(..)) where+import Control.Subcategory.Functor++import qualified Control.Applicative as App++infixl 3 <!>+class CFunctor f => CChoice f where+  (<!>) :: Dom f a => f a -> f a -> f a+  default (<!>) :: App.Alternative f => f a -> f a -> f a+  (<!>) = (App.<|>)+  {-# INLINE (<!>) #-}++class CChoice f => CAlternative f where+  cempty :: Dom f a => f a+  default cempty :: App.Alternative f => f a+  cempty = App.empty+  {-# INLINE cempty #-}+
+ src/Control/Subcategory/Applicative.hs view
@@ -0,0 +1,168 @@+{-# LANGUAGE EmptyCase, StandaloneDeriving, TupleSections #-}+{-# LANGUAGE UndecidableSuperClasses                      #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Control.Subcategory.Applicative+  ( CApplicative(..), defaultRightApply, defaultLeftApply, CApp(..)+  ) where+import Control.Subcategory.Alternative.Class+import Control.Subcategory.Applicative.Class+import Control.Subcategory.Functor+import Control.Subcategory.Pointed++import qualified Control.Applicative             as App+import qualified Control.Monad.ST.Lazy           as LST+import qualified Control.Monad.ST.Strict         as SST+import           Data.Coerce                     (coerce)+import           Data.Functor.Const              (Const)+import           Data.Functor.Identity           (Identity)+import qualified Data.Functor.Product            as SOP+import           Data.Hashable                   (Hashable)+import qualified Data.HashMap.Strict             as HM+import qualified Data.HashSet                    as HS+import qualified Data.IntMap                     as IM+import           Data.List.NonEmpty              (NonEmpty)+import qualified Data.Map                        as Map+import qualified Data.Primitive.Array            as A+import qualified Data.Primitive.SmallArray       as SA+import qualified Data.Semigroup                  as Sem+import qualified Data.Sequence                   as Seq+import qualified Data.Set                        as Set+import qualified Data.Tree                       as Tree+import qualified Data.Vector                     as V+import           GHC.Conc                        (STM)+import           Text.ParserCombinators.ReadP    (ReadP)+import           Text.ParserCombinators.ReadPrec (ReadPrec)++defaultLeftApply :: (Dom f (b1, b2), Dom f b1, Dom f b2, CApplicative f)+                 => f b1 -> f b2 -> f b1+defaultLeftApply a b = uncurry const <$:> pair a b+defaultRightApply :: (Dom f (b1, b2), Dom f b2, Dom f b1, CApplicative f)+                  => f b1 -> f b2 -> f b2+defaultRightApply a b = uncurry (const id) <$:> pair a b++instance Semigroup w => CApplicative (Const w) where+  pair = coerce @(w -> w -> w) (<>)+  (<.>) = coerce @(w -> w -> w) (<>)+  {-# INLINE (<.>) #-}+  (<. ) = coerce @(w -> w -> w) (<>)+  {-# INLINE (<. ) #-}+  ( .>) = coerce @(w -> w -> w) (<>)+  {-# INLINE ( .>) #-}++instance CApplicative []+instance CApplicative IO+instance CApplicative STM+instance CApplicative ReadP+instance CApplicative V.Vector+instance CApplicative SA.SmallArray+instance CApplicative A.Array+instance CApplicative ReadPrec+instance CApplicative (SST.ST s)+instance CApplicative (LST.ST s)+instance CApplicative App.ZipList+instance CApplicative Maybe+instance CApplicative Identity+instance CApplicative Tree.Tree+instance CApplicative Seq.Seq+instance CApplicative Sem.Option+instance CApplicative NonEmpty+instance CApplicative ((->) a)+instance CApplicative (Either a)+instance (CApplicative f, CApplicative g)+      => CApplicative (SOP.Product f g) where+  pair (SOP.Pair a b) (SOP.Pair c d) = SOP.Pair (pair a c) (pair b d)+  SOP.Pair f g <.> SOP.Pair a b = SOP.Pair (f <.> a) (g <.> b)+  {-# INLINE (<.>) #-}+  SOP.Pair f g <. SOP.Pair a b = SOP.Pair (f <. a) (g <. b)+  {-# INLINE (<.) #-}+  SOP.Pair f g .> SOP.Pair a b = SOP.Pair (f .> a) (g .> b)+  {-# INLINE (.>) #-}++class Dom f (g a -> g b) => DomOver f g a b+instance Dom f (g a -> g b) => DomOver f g a b++instance Applicative f => CApplicative (WrapFunctor f)+instance Semigroup w => CApplicative ((,) w) where+  pair (w, a) (u, b) = (w <> u, (a, b))+  {-# INLINE pair #-}+  (w, f) <.> (u, a) = (w <> u, f a)+  {-# INLINE (<.>) #-}+  (w, a) <.  (u, _) = (w <> u, a)+  {-# INLINE (<.) #-}+  (w, _)  .> (u, b) = (w <> u, b)+  {-# INLINE (.>) #-}+instance CApplicative IM.IntMap where+  pair = IM.intersectionWith (,)+  {-# INLINE pair #-}+  (<.>) = IM.intersectionWith id+  {-# INLINE (<.>) #-}+  (<.)  = IM.intersectionWith const+  {-# INLINE (<.) #-}+  (.>)  = IM.intersectionWith $ const id+  {-# INLINE (.>) #-}++instance Ord k => CApplicative (Map.Map k) where+  pair = Map.intersectionWith (,)+  {-# INLINE pair #-}+  (<.>) = Map.intersectionWith id+  {-# INLINE (<.>) #-}+  (<.)  = Map.intersectionWith const+  {-# INLINE (<.) #-}+  (.>)  = Map.intersectionWith $ const id+  {-# INLINE (.>) #-}++instance (Eq k, Hashable k) => CApplicative (HM.HashMap k) where+  pair = HM.intersectionWith (,)+  {-# INLINE pair #-}+  (<.>) = HM.intersectionWith id+  {-# INLINE (<.>) #-}+  (<.)  = HM.intersectionWith const+  {-# INLINE (<.) #-}+  (.>)  = HM.intersectionWith $ const id+  {-# INLINE (.>) #-}++instance CApplicative Set.Set where+  pair as bs = foldMap (\b -> Set.map (,b) as) bs+  {-# INLINE pair #-}+  fs <.> as = foldMap (\f -> Set.map f as) fs+  {-# INLINE (<.>) #-}+  a <. b | Set.null b = Set.empty+         | otherwise  = a+  {-# INLINE (<.) #-}+  a .> b | Set.null a = Set.empty+         | otherwise  = b+  {-# INLINE (.>) #-}++instance CApplicative HS.HashSet where+  pair as bs = foldMap (\b -> HS.map (,b) as) bs+  {-# INLINE pair #-}+  fs <.> as = foldMap (\f -> HS.map f as) fs+  {-# INLINE (<.>) #-}+  a <. b | HS.null b = HS.empty+         | otherwise  = a+  {-# INLINE (<.) #-}+  a .> b | HS.null a = HS.empty+         | otherwise  = b+  {-# INLINE (.>) #-}++instance Constrained f => Constrained (CApp f) where+  type Dom (CApp f) a = Dom f a++newtype CApp f a = CApp { runCApp :: f a }+  deriving (Read, Show, Eq, Ord)+  deriving newtype (Functor, Applicative, App.Alternative)++deriving newtype instance (CFunctor f) => CFunctor (CApp f)+deriving newtype instance (CChoice f) => CChoice (CApp f)+deriving newtype instance (CAlternative f) => CAlternative (CApp f)+deriving newtype instance (CApplicative f) => CApplicative (CApp f)+deriving newtype instance (CPointed f) => CPointed (CApp f)++instance (Dom f a, CApplicative f, Semigroup a, Dom f (a, a))+       => Semigroup (CApp f a) where+  CApp a <> CApp b = CApp $ uncurry (<>) <$:> pair a b++instance (Dom f a, CPointed f, CApplicative f, Monoid a, Dom f (a, a))+       => Monoid (CApp f a) where+  CApp a `mappend` CApp b = CApp $ uncurry mappend <$:> pair a b+  mempty = CApp $ cpure mempty
+ src/Control/Subcategory/Applicative/Class.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE EmptyCase, UndecidableSuperClasses #-}+module Control.Subcategory.Applicative.Class  (CApplicative(..)) where+import Control.Subcategory.Functor++import qualified Control.Applicative as App++infixl 4 <.>+class CFunctor f => CApplicative f where+  pair :: (Dom f a, Dom f b, Dom f (a, b)) => f a -> f b -> f (a, b)+  default pair :: (Applicative f) => f a -> f b -> f (a, b)+  pair = App.liftA2 (,)+  (<.>) :: (Dom f a, Dom f b, Dom f (a -> b)) => f (a -> b) -> f a -> f b+  default (<.>) :: (Applicative f) => f (a -> b) -> f a -> f b+  (<.>) = (<*>)+  (.>) :: (Dom f a, Dom f b) => f a -> f b -> f b+  default (.>) :: Applicative f+               => f a -> f b -> f b+  (.>) = (*>)+  (<.) :: (Dom f a, Dom f b) => f a -> f b -> f a+  default (<.) :: Applicative f+               => f a -> f b -> f a+  (<.) = (<*)
+ src/Control/Subcategory/Bind.hs view
@@ -0,0 +1,147 @@+module Control.Subcategory.Bind+  (CBind(..), CMonad, creturn, (-<<)) where+import Control.Subcategory.Functor+import Control.Subcategory.Pointed++import           Control.Monad                   (join)+import qualified Control.Monad.ST.Lazy           as LST+import qualified Control.Monad.ST.Strict         as SST+import           Data.Coerce                     (coerce)+import           Data.Functor.Identity           (Identity)+import qualified Data.Functor.Product            as SOP+import           Data.Hashable                   (Hashable)+import qualified Data.HashMap.Strict             as HM+import qualified Data.HashSet                    as HS+import qualified Data.IntMap                     as IM+import qualified Data.IntSet                     as IS+import           Data.List.NonEmpty              (NonEmpty)+import qualified Data.Map                        as Map+import           Data.MonoTraversable+import qualified Data.Semigroup                  as Sem+import qualified Data.Sequence                   as Seq+import qualified Data.Set                        as Set+import qualified Data.Tree                       as Tree+import           GHC.Conc                        (STM)+import           Text.ParserCombinators.ReadP    (ReadP)+import           Text.ParserCombinators.ReadPrec (ReadPrec)++class CFunctor m => CBind m where+  (>>-) :: (Dom m a, Dom m b) => m a -> (a -> m b) -> m b+  default (>>-) :: (Dom m a, Dom m b, Dom m (m b)) => m a -> (a -> m b) -> m b+  m >>- f = cjoin (cmap f m)+  cjoin :: (Dom m (m a), Dom m a) => m (m a) -> m a+  cjoin = (>>- id)++instance (Monad m) => CBind (WrapFunctor m) where+  (>>-) :: forall a b.+           WrapFunctor m a+        -> (a -> WrapFunctor m b) -> WrapFunctor m b+  (>>-) = coerce @(m a -> (a -> m b) -> m b) (>>=)+  cjoin :: forall a. WrapFunctor m (WrapFunctor m a) -> WrapFunctor m a+  cjoin (WrapFunctor m) = WrapFunctor $ join (fmap coerce m)++instance CBind [] where+  (>>-) = (>>=)+  cjoin  = concat++instance CBind IO where+  (>>-) = (>>=)++instance CBind STM where+  (>>-) = (>>=)++instance CBind (SST.ST s) where+  (>>-) = (>>=)++instance CBind (LST.ST s) where+  (>>-) = (>>=)++instance CBind Identity where+  (>>-) = (>>=)++instance CBind (Either a) where+  (>>-) = (>>=)++instance CBind Tree.Tree where+  (>>-) = (>>=)++instance CBind Maybe where+  (>>-) = (>>=)++instance CBind IM.IntMap where+  m >>- f = IM.mapMaybeWithKey (\k -> IM.lookup k . f) m++instance Ord k => CBind (Map.Map k) where+  m >>- f = Map.mapMaybeWithKey (\k -> Map.lookup k . f) m++instance (Hashable k, Eq k) => CBind (HM.HashMap k) where+  m >>- f = HM.mapMaybeWithKey (\k -> HM.lookup k . f) m++instance CBind Set.Set where+  (>>-) = flip foldMap+  {-# INLINE (>>-) #-}+  cjoin = foldMap id+  {-# INLINE cjoin #-}++instance CBind (WrapMono IS.IntSet) where+  (>>-) = withMonoCoercible $ flip ofoldMap+  {-# INLINE (>>-) #-}++instance CBind NonEmpty where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance CBind Seq.Seq where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance CBind Sem.Option where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance CBind ((->) a) where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance CBind HS.HashSet where+  (>>-) = flip foldMap+  {-# INLINE (>>-) #-}+  cjoin = foldMap id+  {-# INLINE cjoin #-}++instance CBind ReadP where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance CBind ReadPrec where+  (>>-) = (>>=)+  {-# INLINE (>>-) #-}++instance Semigroup w => CBind ((,) w) where+  (m, a) >>- f =+    let (w, b) = f a+    in (m <> w, b)+  {-# INLINE (>>-) #-}+  cjoin (w, (m, a)) = (w <> m, a)+  {-# INLINE cjoin #-}++infixl 1 >>-+infixr 1 -<<++(-<<) :: (Dom m b, Dom m a, CBind m) => (a -> m b) -> m a -> m b+(-<<) = flip (>>-)+{-# INLINE (-<<) #-}++instance (CBind m, CBind n) => CBind (SOP.Product m n) where+  (SOP.Pair a b) >>- f = SOP.Pair (a >>- fstP . f) (b >>- sndP . f)+    where+      fstP (SOP.Pair x _) = x+      sndP (SOP.Pair _ y) = y+  {-# INLINE (>>-) #-}++class    (CBind f, CPointed f) => CMonad f+instance (CBind f, CPointed f) => CMonad f++creturn :: (Dom m a, CMonad m) => a -> m a+creturn = cpure+{-# INLINE creturn #-}
+ src/Control/Subcategory/Foldable.hs view
@@ -0,0 +1,1606 @@+{-# LANGUAGE BangPatterns, CPP, DefaultSignatures, DerivingVia, LambdaCase #-}+{-# LANGUAGE OverloadedStrings, QuantifiedConstraints, StandaloneDeriving  #-}+{-# LANGUAGE TemplateHaskell, TypeOperators                                #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Control.Subcategory.Foldable+  ( CFoldable(..),+    ctoList,+    CTraversable(..),+    CFreeMonoid(..),+    cfromList,+    cfolded, cfolding,+    cctraverseFreeMonoid,+    cctraverseZipFreeMonoid+  ) where+import           Control.Applicative                  (ZipList, getZipList)+import           Control.Arrow                        (first, second, (***))+import qualified Control.Foldl                        as L+import           Control.Monad                        (forM)+import           Control.Subcategory.Applicative+import           Control.Subcategory.Functor+import           Control.Subcategory.Pointed+import           Control.Subcategory.Wrapper.Internal+import           Control.Subcategory.Zip+import           Data.Coerce+import           Data.Complex                         (Complex)+import           Data.Foldable+import           Data.Functor.Const                   (Const)+import           Data.Functor.Contravariant           (Contravariant, contramap,+                                                       phantom)+import           Data.Functor.Identity                (Identity)+import qualified Data.Functor.Product                 as SOP+import qualified Data.Functor.Sum                     as SOP+import qualified Data.HashMap.Strict                  as HM+import qualified Data.HashSet                         as HS+import qualified Data.IntMap.Strict                   as IM+import qualified Data.IntSet                          as IS+import           Data.Kind                            (Type)+import           Data.List                            (uncons)+import           Data.List                            (intersperse)+import           Data.List                            (nub)+import qualified Data.List                            as List+import           Data.List.NonEmpty                   (NonEmpty)+import qualified Data.List.NonEmpty                   as NE+import qualified Data.Map                             as M+import           Data.Maybe+import           Data.Monoid+import qualified Data.Monoid                          as Mon+import           Data.MonoTraversable                 hiding (WrappedMono,+                                                       unwrapMono)+import           Data.Ord                             (Down)+import qualified Data.Primitive.Array                 as A+import qualified Data.Primitive.PrimArray             as PA+import qualified Data.Primitive.SmallArray            as SA+import           Data.Proxy                           (Proxy)+import           Data.Semigroup                       (Arg, Max (..), Min (..),+                                                       Option)+import qualified Data.Semigroup                       as Sem+import qualified Data.Sequence                        as Seq+import           Data.Sequences                       (IsSequence (indexEx))+import qualified Data.Sequences                       as MT+import qualified Data.Set                             as Set+import qualified Data.Text                            as T+import qualified Data.Vector                          as V+import qualified Data.Vector.Algorithms.Intro         as AI+import qualified Data.Vector.Primitive                as P+import qualified Data.Vector.Storable                 as S+import qualified Data.Vector.Unboxed                  as U+import           Foreign.Ptr                          (Ptr)+import qualified GHC.Exts                             as GHC+import           GHC.Generics+import           Language.Haskell.TH                  hiding (Type)+import           Language.Haskell.TH.Syntax           hiding (Type)+import qualified VectorBuilder.Builder                as VB+import qualified VectorBuilder.Vector                 as VB++-- See Note [Function coercion]+(#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c)+(#.) _f = coerce+{-# INLINE (#.) #-}++ctoList :: (CFoldable f, Dom f a) => f a -> [a]+{-# INLINE [1] ctoList #-}+ctoList = cbasicToList++cfromList :: (CFreeMonoid f, Dom f a) => [a] -> f a+{-# INLINE [1] cfromList #-}+cfromList = cbasicFromList+++-- | Fold-optic for 'CFoldable' instances.+--   In the terminology of lens, cfolded is a constrained+--   variant of @folded@ optic.+--+--  @+--    cfolded :: (CFoldable t, Dom t a) => Fold (t a) a+--  @+cfolded+  :: (CFoldable t, Dom t a)+  => forall f. (Contravariant f, Applicative f) => (a -> f a) -> t a -> f (t a)+{-# INLINE cfolded #-}+cfolded = (contramap (const ()) .) . ctraverse_++class Constrained f => CFoldable f where+  {-# MINIMAL cfoldMap | cfoldr #-}+  cfoldMap :: (Dom f a, Monoid w) => (a -> w) -> f a -> w+  {-# INLINE [1] cfoldMap #-}+  cfoldMap f = cfoldr (mappend . f) mempty++  cfoldMap' :: (Dom f a, Monoid m) => (a -> m) -> f a -> m+  {-# INLINE [1] cfoldMap' #-}+  cfoldMap' f = cfoldl' (\ acc a -> acc <> f a) mempty++  cfold :: (Dom f w, Monoid w) => f w -> w+  cfold = cfoldMap id++  {-# INLINE [1] cfold #-}+  cfoldr :: (Dom f a) => (a -> b -> b) -> b -> f a -> b+  {-# INLINE [1] cfoldr #-}+  cfoldr f z t = appEndo (cfoldMap (Endo #. f) t) z++  cfoldlM+    :: (Monad m, Dom f b)+    => (a -> b -> m a) -> a -> f b -> m a+  {-# INLINE [1] cfoldlM #-}+  cfoldlM f z0 xs = cfoldr f' return xs z0+    where f' x k z = f z x >>= k++  cfoldlM'+    :: (Monad m, Dom f b)+    => (a -> b -> m a) -> a -> f b -> m a+  {-# INLINE [1] cfoldlM' #-}+  cfoldlM' f z0 xs = cfoldr' f' return xs z0+    where f' !x k z = do+            !i <- f z x+            k i++  cfoldrM+    :: (Monad m, Dom f a)+    => (a -> b -> m b) -> b -> f a -> m b+  {-# INLINE [1] cfoldrM #-}+  cfoldrM f z0 xs = cfoldl c return xs z0+    where c k x z = f x z >>= k++  cfoldrM'+    :: (Monad m, Dom f a)+    => (a -> b -> m b) -> b -> f a -> m b+  {-# INLINE [1] cfoldrM' #-}+  cfoldrM' f z0 xs = cfoldl' c return xs z0+    where c k !x z = do+            !i <- f x z+            k i+  cfoldl+      :: (Dom f a)+      => (b -> a -> b) -> b -> f a -> b+  {-# INLINE [1] cfoldl #-}+  cfoldl f z t = appEndo (getDual (cfoldMap (Dual . Endo . flip f) t)) z++  cfoldr' :: (Dom f a) => (a -> b -> b) -> b -> f a -> b+  {-# INLINE [1] cfoldr' #-}+  cfoldr' f z0 xs = cfoldl f' id xs z0+      where f' k x z = k $! f x z++  cfoldl' :: Dom f a => (b -> a -> b) -> b -> f a -> b+  {-# INLINE [1] cfoldl' #-}+  cfoldl' f z0 xs = cfoldr f' id xs z0+    where f' x k z = k $! f z x++  cbasicToList :: Dom f a => f a -> [a]+  {-# INLINE cbasicToList #-}+  cbasicToList = cfoldr (:) []++  cfoldr1 :: Dom f a => (a -> a -> a) -> f a -> a+  {-# INLINE [1] cfoldr1 #-}+  cfoldr1 f xs = fromMaybe (errorWithoutStackTrace "cfoldr1: empty structure")+                    (cfoldr mf Nothing xs)+      where+        mf x m = Just $+          case m of+            Nothing -> x+            Just y  -> f x y++++  cfoldl1 :: Dom f a => (a -> a -> a) -> f a -> a+  {-# INLINE [1] cfoldl1 #-}+  cfoldl1 f xs = fromMaybe (errorWithoutStackTrace "cfoldl1: empty structure")+                  (cfoldl mf Nothing xs)+    where+      mf m y = Just $+        case m of+          Nothing -> y+          Just x  -> f x y++  cindex :: Dom f a => f a -> Int -> a+  cindex xs n = case cfoldl' go (Left' 0) xs of+    Right' x -> x+    Left'{} -> errorWithoutStackTrace $ "cindex: index out of bound " ++ show n+    where+      go (Left' i) x+        | i == n = Right' x+        | otherwise = Left' (i + 1)+      go r@Right'{} _ = r++  cnull :: Dom f a => f a -> Bool+  cnull = cfoldr (const $ const False) True++  clength :: Dom f a => f a -> Int+  {-# INLINE [1] clength #-}+  clength = cfoldl' (\c _ -> c + 1) 0++  cany :: Dom f a => (a -> Bool) -> f a -> Bool+  {-# INLINE [1] cany #-}+  cany p = cfoldl' (\b -> (||) b . p) False++  call :: Dom f a => (a -> Bool) -> f a -> Bool+  {-# INLINE [1] call #-}+  call p = cfoldl' (\b -> (&&) b . p) True++  celem :: (Eq a, Dom f a) => a -> f a -> Bool+  {-# INLINE [1] celem #-}+  celem = cany . (==)++  cnotElem :: (Eq a, Dom f a) => a -> f a -> Bool+  {-# INLINE [1] cnotElem #-}+  cnotElem = call . (/=)++  cminimum :: (Ord a, Dom f a) => f a -> a+  {-# INLINE [1] cminimum #-}+  cminimum =+    getMin+    . fromMaybe (errorWithoutStackTrace "minimum: empty structure")+    . cfoldMap (Just . Min)++  cmaximum :: (Ord a, Dom f a) => f a -> a+  {-# INLINE [1] cmaximum #-}+  cmaximum =+    getMax+    . fromMaybe (errorWithoutStackTrace "cmaximum: empty structure")+    . cfoldMap (Just . Max)++  csum :: (Num a, Dom f a) => f a -> a+  {-# INLINE [1] csum #-}+  csum = getSum #. cfoldMap Sum++  cproduct :: (Num a, Dom f a) => f a -> a+  {-# INLINE [1] cproduct #-}+  cproduct = getProduct #. cfoldMap Product++  cctraverse_+    :: (CApplicative g, CPointed g, Dom g (), Dom f a, Dom g b)+    => (a -> g b)+    -> f a -> g ()+  {-# INLINE [1] cctraverse_ #-}+  cctraverse_ f = cfoldr c (cpure ())+    where+      {-# INLINE c #-}+      c x k = f x .> k++  ctraverse_+    :: (Applicative g, Dom f a)+    => (a -> g b)+    -> f a -> g ()+  {-# INLINE [1] ctraverse_ #-}+  ctraverse_ f = cfoldr c (pure ())+    where+      {-# INLINE c #-}+      c x k = f x *> k++  clast :: Dom f a => f a -> a+  {-# INLINE [1] clast #-}+  clast = fromJust . L.foldOver cfolded L.last++  chead :: Dom f a => f a -> a+  {-# INLINE [1] chead #-}+  chead = fromJust . L.foldOver cfolded L.head++  cfind :: Dom f a => (a -> Bool) -> f a -> Maybe a+  {-# INLINE [1] cfind #-}+  cfind = \p -> getFirst . cfoldMap (\x -> First $ if p x then Just x else Nothing)++  cfindIndex :: Dom f a => (a -> Bool) -> f a -> Maybe Int+  {-# INLINE [1] cfindIndex #-}+  cfindIndex = \p -> L.foldOver cfolded (L.findIndex p)++  cfindIndices :: Dom f a => (a -> Bool) -> f a -> [Int]+  {-# INLINE [1] cfindIndices #-}+  cfindIndices = \p -> List.findIndices p . ctoList++  celemIndex :: (Dom f a, Eq a) => a -> f a -> Maybe Int+  {-# INLINE [0] celemIndex #-}+  celemIndex = cfindIndex . (==)++  celemIndices :: (Dom f a, Eq a) => a -> f a -> [Int]+  {-# INLINE [0] celemIndices #-}+  celemIndices = cfindIndices . (==)++data Eith' a b = Left' !a | Right' !b++instance Traversable f => CTraversable (WrapFunctor f) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}++instance Foldable f => CFoldable (WrapFunctor f) where+  cfoldMap = foldMap+  {-# INLINE [1] cfoldMap #-}+#if MIN_VERSION_base(4,13,0)+  cfoldMap' = foldMap'+  {-# INLINE [1] cfoldMap' #-}+#endif+  cfold = fold+  {-# INLINE [1] cfold #-}+  cfoldr = foldr+  {-# INLINE [1] cfoldr #-}+  cfoldr' = foldr'+  {-# INLINE [1] cfoldr' #-}+  cfoldl = foldl+  {-# INLINE [1] cfoldl #-}+  cfoldl' = foldl'+  {-# INLINE [1] cfoldl' #-}+  cbasicToList = toList+  {-# INLINE [1] cbasicToList #-}+  cfoldr1 = foldr1+  {-# INLINE [1] cfoldr1 #-}+  cfoldl1 = foldl1+  {-# INLINE [1] cfoldl1 #-}+  cfoldlM = foldlM+  {-# INLINE [1] cfoldlM #-}+  cfoldrM = foldrM+  {-# INLINE [1] cfoldrM #-}+  cnull = null+  {-# INLINE [1] cnull #-}+  clength = length+  {-# INLINE [1] clength #-}+  cany = any+  {-# INLINE [1] cany #-}+  call = all+  {-# INLINE [1] call #-}+  celem = elem+  {-# INLINE [1] celem #-}+  cnotElem = notElem+  {-# INLINE [1] cnotElem #-}+  cminimum = minimum+  {-# INLINE [1] cminimum #-}+  cmaximum = maximum+  {-# INLINE [1] cmaximum #-}+  csum = sum+  {-# INLINE [1] csum #-}+  cproduct = product+  {-# INLINE [1] cproduct #-}+  ctraverse_ = traverse_+  {-# INLINE [1] ctraverse_ #-}+  cfind = find+  {-# INLINE [1] cfind #-}+  cfindIndex = L.fold . L.findIndex+  {-# INLINE [1] cfindIndex #-}+  celemIndex = L.fold . L.elemIndex+  {-# INLINE [1] celemIndex #-}++{-# RULES+"cfind/List"+  cfind = find @[]++"cfindIndex/List"+  cfindIndex = List.findIndex++"cfindIndices/List"+  cfindIndices = List.findIndices++"celemIndex/List"+  celemIndex = List.elemIndex++"celemIndices/List"+  celemIndices = List.elemIndices++"cfindIndex/List"+  cfindIndex = Seq.findIndexL++"cfindIndices/Seq"+  cfindIndices = Seq.findIndicesL++"celemIndex/Seq"+  celemIndex = Seq.elemIndexL++"celemIndices/Seq"+  celemIndices = Seq.elemIndicesL++  #-}++{-# RULES+"cctraverse_/traverse_"+  forall (f :: Applicative f => a -> f b) (tx :: Foldable t => t a).+  cctraverse_ f tx = traverse_ f tx+  #-}++{-# RULES+"cindex/List"+  cindex = (!!)+  #-}++class (CFunctor f, CFoldable f) => CTraversable f where+  -- | __N.B.__ If we require @g@ to be 'CApplicative'+  --   we cannot directly lift plain 'Traversable' to 'CTraversable'.+  --   This is rather annoying, so we require the strongest possible+  --   constraint to @g@ here.+  ctraverse+    :: (Dom f a, Dom f b, Applicative g)+    => (a -> g b) -> f a -> g (f b)++deriving via WrapFunctor []+  instance CFoldable []+{-# RULES+"ctoList/List"+  ctoList = id+"cfromList/List"+  cbasicFromList = id+"clast/List"+  clast = last+"chead/List"+  chead = head+  #-}++instance CTraversable [] where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Maybe+  instance CFoldable Maybe+instance CTraversable Maybe where+  ctraverse = traverse+deriving via WrapFunctor (Either e)+  instance CFoldable (Either e)+instance CTraversable (Either e) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor IM.IntMap+  instance CFoldable IM.IntMap+instance CTraversable IM.IntMap where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (M.Map k)+  instance CFoldable (M.Map k)+instance Ord k => CTraversable (M.Map k) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (HM.HashMap k)+  instance CFoldable (HM.HashMap k)+instance CTraversable (HM.HashMap k) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Seq.Seq+  instance CFoldable Seq.Seq+instance CTraversable Seq.Seq where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+{-# RULES+"cindex/Seq"+  cindex = Seq.index+  #-}++deriving via WrapFunctor Par1+  instance CFoldable Par1+instance CTraversable Par1 where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor NonEmpty+  instance CFoldable NonEmpty+instance CTraversable NonEmpty where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+{-# RULES+"cindex/NonEmpty"+  cindex = (NE.!!)+  #-}++deriving via WrapFunctor Down+  instance CFoldable Down+instance CTraversable Down where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Mon.Last+  instance CFoldable Mon.Last+instance CTraversable Mon.Last where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Mon.First+  instance CFoldable Mon.First+instance CTraversable Mon.First where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Sem.Last+  instance CFoldable Sem.Last+instance CTraversable Sem.Last where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Sem.First+  instance CFoldable Sem.First+instance CTraversable Sem.First where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Identity+  instance CFoldable Identity+instance CTraversable Identity where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor ZipList+  instance CFoldable ZipList+instance CTraversable ZipList where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+{-# RULES+"cindex/ZipList"+  cindex = (!!) . getZipList+  #-}++deriving via WrapFunctor Option+  instance CFoldable Option+instance CTraversable Option where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Min+  instance CFoldable Min+instance CTraversable Min where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Max+  instance CFoldable Max+instance CTraversable Max where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor Complex+  instance CFoldable Complex+instance CTraversable Complex where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (V1 :: Type -> Type)+  instance CFoldable (V1 :: Type -> Type)+instance CTraversable (V1 :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (U1 :: Type -> Type)+  instance CFoldable (U1 :: Type -> Type)+instance CTraversable (U1 :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor ((,) a)+  instance CFoldable ((,) a)+instance CTraversable ((,) a) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (Proxy :: Type -> Type)+  instance CFoldable (Proxy :: Type -> Type)+instance CTraversable (Proxy :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (Arg a)+  instance CFoldable (Arg a)+instance CTraversable (Arg a) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (Rec1 (f :: Type -> Type))+  instance Foldable f => CFoldable (Rec1 (f :: Type -> Type))+deriving via WrapFunctor (URec Char :: Type -> Type)+  instance CFoldable (URec Char :: Type -> Type)+instance CTraversable (URec Char :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (URec Double :: Type -> Type)+  instance CFoldable (URec Double :: Type -> Type)+instance CTraversable (URec Double :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (URec Float :: Type -> Type)+  instance CFoldable (URec Float :: Type -> Type)+instance CTraversable (URec Float :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (URec Int :: Type -> Type)+  instance CFoldable (URec Int :: Type -> Type)+instance CTraversable (URec Int :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (URec Word :: Type -> Type)+  instance CFoldable (URec Word :: Type -> Type)+instance CTraversable (URec Word :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (URec (Ptr ()) :: Type -> Type)+  instance CFoldable (URec (Ptr ()) :: Type -> Type)+instance CTraversable (URec (Ptr ()) :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving newtype+  instance CFoldable f => CFoldable (Alt f)+deriving newtype+  instance CFoldable f => CFoldable (Ap f)+deriving via WrapFunctor (Const m :: Type -> Type)+  instance CFoldable (Const m :: Type -> Type)+instance CTraversable (Const m :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}+deriving via WrapFunctor (K1 i c :: Type -> Type)+  instance CFoldable (K1 i c :: Type -> Type)+instance CTraversable (K1 i c :: Type -> Type) where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}++instance (CFoldable f, CFoldable g) => CFoldable (f :+: g) where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap f = \case+    L1 x -> cfoldMap f x+    R1 x -> cfoldMap f x++  {-# INLINE [1] cfoldr #-}+  cfoldr f z = \case+    L1 x -> cfoldr f z x+    R1 x -> cfoldr f z x++  cfoldMap' = \f -> \case+    L1 x -> cfoldMap' f x+    R1 x -> cfoldMap' f x+  {-# INLINE [1] cfoldMap' #-}+  cfold = \case+    L1 x -> cfold x+    R1 x -> cfold x+  {-# INLINE [1] cfold #-}+  cfoldr' = \f z -> \case+    L1 x -> cfoldr' f z x+    R1 x -> cfoldr' f z x+  {-# INLINE [1] cfoldr' #-}+  cfoldl = \f z -> \case+    L1 x -> cfoldl f z x+    R1 x -> cfoldl f z x+  {-# INLINE [1] cfoldl #-}+  cfoldl' = \f z -> \case+    L1 x -> cfoldl' f z x+    R1 x -> cfoldl' f z x+  {-# INLINE [1] cfoldl' #-}+  cbasicToList = \case+    L1 x -> ctoList x+    R1 x -> ctoList x+  {-# INLINE cbasicToList #-}+  cfoldr1 = \f -> \case+    L1 x -> cfoldr1 f x+    R1 x -> cfoldr1 f x+  {-# INLINE [1] cfoldr1 #-}+  cfoldl1 = \f -> \case+    L1 x -> cfoldl1 f x+    R1 x -> cfoldl1 f x+  {-# INLINE [1] cfoldl1 #-}+  cnull = \case+    L1 x -> cnull x+    R1 x -> cnull x+  {-# INLINE [1] cnull #-}+  clength = \case+    L1 x -> clength x+    R1 x -> clength x+  {-# INLINE [1] clength #-}+  cany = \f -> \case+    L1 x -> cany f x+    R1 x -> cany f x+  {-# INLINE [1] cany #-}+  call = \f -> \case+    L1 x -> call f x+    R1 x -> call f x+  {-# INLINE [1] call #-}+  celem = \x -> \case+    L1 xs -> celem x xs+    R1 xs -> celem x xs+  {-# INLINE [1] celem #-}+  cminimum = \case+    L1 xs -> cminimum xs+    R1 xs -> cminimum xs+  {-# INLINE [1] cminimum #-}+  cmaximum = \case+    L1 xs -> cmaximum xs+    R1 xs -> cmaximum xs+  {-# INLINE [1] cmaximum #-}+  csum = \case+    L1 xs -> csum xs+    R1 xs -> csum xs+  {-# INLINE [1] csum #-}+  cproduct = \case+    L1 xs -> cproduct xs+    R1 xs -> cproduct xs+  {-# INLINE [1] cproduct #-}+  ctraverse_ f = \case+    L1 xs -> ctraverse_ f xs+    R1 xs -> ctraverse_ f xs+  {-# INLINE [1] ctraverse_ #-}++instance (CTraversable f, CTraversable g) => CTraversable (f :+: g) where+  ctraverse f = \case+    L1 xs -> L1 <$> ctraverse f xs+    R1 xs -> R1 <$> ctraverse f xs+  {-# INLINE [1] ctraverse #-}++instance (CFoldable f, CFoldable g) => CFoldable (f :*: g) where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap f (l :*: r) = cfoldMap f l <> cfoldMap f r++  cfoldMap' f (l :*: r) = cfoldMap' f l <> cfoldMap' f r+  {-# INLINE [1] cfoldMap' #-}+  cfold (l :*: r) = cfold l <> cfold r+  {-# INLINE [1] cfold #-}+  cnull (l :*: r) = cnull l && cnull r+  {-# INLINE [1] cnull #-}+  clength (l :*: r) = clength l + clength r+  {-# INLINE [1] clength #-}+  cany f (l :*: r) = cany f l || cany f r+  {-# INLINE [1] cany #-}+  call f (l :*: r) = call f l && call f r+  {-# INLINE [1] call #-}+  celem x (l :*: r) = celem x l || celem x r+  {-# INLINE [1] celem #-}+  csum (l :*: r) = csum l + csum r+  {-# INLINE [1] csum #-}+  cproduct (l :*: r) = cproduct l * cproduct r+  {-# INLINE [1] cproduct #-}+  ctraverse_ f (l :*: r) = ctraverse_ f l *> ctraverse_ f r+  {-# INLINE [1] ctraverse_ #-}++instance (CTraversable f, CTraversable g) => CTraversable (f :*: g) where+  ctraverse f (l :*: r) =+    (:*:) <$> ctraverse f l <*> ctraverse f r++instance (CFoldable f, CFoldable g) => CFoldable (SOP.Sum f g) where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap f = \case+    SOP.InL x -> cfoldMap f x+    SOP.InR x -> cfoldMap f x++  {-# INLINE [1] cfoldr #-}+  cfoldr f z = \case+    SOP.InL x -> cfoldr f z x+    SOP.InR x -> cfoldr f z x++  cfoldMap' = \f -> \case+    SOP.InL x -> cfoldMap' f x+    SOP.InR x -> cfoldMap' f x+  {-# INLINE [1] cfoldMap' #-}+  cfold = \case+    SOP.InL x -> cfold x+    SOP.InR x -> cfold x+  {-# INLINE [1] cfold #-}+  cfoldr' = \f z -> \case+    SOP.InL x -> cfoldr' f z x+    SOP.InR x -> cfoldr' f z x+  {-# INLINE [1] cfoldr' #-}+  cfoldl = \f z -> \case+    SOP.InL x -> cfoldl f z x+    SOP.InR x -> cfoldl f z x+  {-# INLINE [1] cfoldl #-}+  cfoldl' = \f z -> \case+    SOP.InL x -> cfoldl' f z x+    SOP.InR x -> cfoldl' f z x+  {-# INLINE [1] cfoldl' #-}+  cbasicToList = \case+    SOP.InL x -> ctoList x+    SOP.InR x -> ctoList x+  {-# INLINE cbasicToList #-}+  cfoldr1 = \f -> \case+    SOP.InL x -> cfoldr1 f x+    SOP.InR x -> cfoldr1 f x+  {-# INLINE [1] cfoldr1 #-}+  cfoldl1 = \f -> \case+    SOP.InL x -> cfoldl1 f x+    SOP.InR x -> cfoldl1 f x+  {-# INLINE [1] cfoldl1 #-}+  cnull = \case+    SOP.InL x -> cnull x+    SOP.InR x -> cnull x+  {-# INLINE [1] cnull #-}+  clength = \case+    SOP.InL x -> clength x+    SOP.InR x -> clength x+  {-# INLINE [1] clength #-}+  cany = \f -> \case+    SOP.InL x -> cany f x+    SOP.InR x -> cany f x+  {-# INLINE [1] cany #-}+  call = \f -> \case+    SOP.InL x -> call f x+    SOP.InR x -> call f x+  {-# INLINE [1] call #-}+  celem = \x -> \case+    SOP.InL xs -> celem x xs+    SOP.InR xs -> celem x xs+  {-# INLINE [1] celem #-}+  cminimum = \case+    SOP.InL xs -> cminimum xs+    SOP.InR xs -> cminimum xs+  {-# INLINE [1] cminimum #-}+  cmaximum = \case+    SOP.InL xs -> cmaximum xs+    SOP.InR xs -> cmaximum xs+  {-# INLINE [1] cmaximum #-}+  csum = \case+    SOP.InL xs -> csum xs+    SOP.InR xs -> csum xs+  {-# INLINE [1] csum #-}+  cproduct = \case+    SOP.InL xs -> cproduct xs+    SOP.InR xs -> cproduct xs+  {-# INLINE [1] cproduct #-}+  ctraverse_ f = \case+    SOP.InL xs -> ctraverse_ f xs+    SOP.InR xs -> ctraverse_ f xs+  {-# INLINE [1] ctraverse_ #-}++instance (CTraversable f, CTraversable g) => CTraversable (SOP.Sum f g) where+  ctraverse f = \case+    SOP.InL xs -> SOP.InL <$> ctraverse f xs+    SOP.InR xs -> SOP.InR <$> ctraverse f xs+  {-# INLINE [1] ctraverse #-}++instance (CFoldable f, CFoldable g) => CFoldable (SOP.Product f g) where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap f (SOP.Pair l r) = cfoldMap f l <> cfoldMap f r++  cfoldMap' f (SOP.Pair l r) = cfoldMap' f l <> cfoldMap' f r+  {-# INLINE [1] cfoldMap' #-}+  cfold (SOP.Pair l r) = cfold l <> cfold r+  {-# INLINE [1] cfold #-}+  cnull (SOP.Pair l r) = cnull l && cnull r+  {-# INLINE [1] cnull #-}+  clength (SOP.Pair l r) = clength l + clength r+  {-# INLINE [1] clength #-}+  cany f (SOP.Pair l r) = cany f l || cany f r+  {-# INLINE [1] cany #-}+  call f (SOP.Pair l r) = call f l && call f r+  {-# INLINE [1] call #-}+  celem x (SOP.Pair l r) = celem x l || celem x r+  {-# INLINE [1] celem #-}+  csum (SOP.Pair l r) = csum l + csum r+  {-# INLINE [1] csum #-}+  cproduct (SOP.Pair l r) = cproduct l * cproduct r+  {-# INLINE [1] cproduct #-}+  ctraverse_ f (SOP.Pair l r) =+    ctraverse_ f l *> ctraverse_ f r+  {-# INLINE ctraverse_ #-}++deriving via WrapFunctor SA.SmallArray instance CFoldable SA.SmallArray+deriving via WrapFunctor A.Array instance CFoldable A.Array++instance CFoldable PA.PrimArray where+  cfoldr = PA.foldrPrimArray+  {-# INLINE [1] cfoldr #-}+  cfoldl' = PA.foldlPrimArray'+  {-# INLINE [1] cfoldl' #-}+  cfoldlM' = PA.foldlPrimArrayM'+  {-# INLINE [1] cfoldlM' #-}+  cfoldl = PA.foldlPrimArray+  {-# INLINE [1] cfoldl #-}+  clength = PA.sizeofPrimArray+  {-# INLINE [1] clength #-}+  csum = PA.foldlPrimArray' (+) 0+  {-# INLINE [1] csum #-}+  cproduct = PA.foldlPrimArray' (*) 1+  {-# INLINE [1] cproduct #-}+  ctraverse_ = PA.traversePrimArray_+  {-# INLINE [1] ctraverse_ #-}++instance CTraversable PA.PrimArray where+  ctraverse = PA.traversePrimArray+  {-# INLINE [1] ctraverse #-}++instance CTraversable SA.SmallArray where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}++instance CTraversable A.Array where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}++instance (CTraversable f, CTraversable g) => CTraversable (SOP.Product f g) where+  {-# INLINE [1] ctraverse #-}+  ctraverse f (SOP.Pair l r) =+    SOP.Pair <$> ctraverse f l <*> ctraverse f r++instance CFoldable Set.Set where+  cfoldMap = ofoldMap+  {-# INLINE [1] cfoldMap #-}+  cfoldr = Set.foldr+  {-# INLINE [1] cfoldr #-}+  cfoldl = Set.foldl+  {-# INLINE [1] cfoldl #-}+  cfoldr' = Set.foldr'+  {-# INLINE [1] cfoldr' #-}+  cfoldl' = Set.foldl'+  {-# INLINE [1] cfoldl' #-}+  cminimum = Set.findMin+  {-# INLINE [1] cminimum #-}+  cmaximum = Set.findMax+  {-# INLINE [1] cmaximum #-}+  celem = Set.member+  {-# INLINE [1] celem #-}+  cnotElem = Set.notMember+  {-# INLINE [1] cnotElem #-}+  cbasicToList = Set.toList+  {-# INLINE cbasicToList #-}+  celemIndex = Set.lookupIndex+  {-# INLINE [1] celemIndex #-}+  cindex = flip Set.elemAt+  {-# INLINE [1] cindex #-}++instance CTraversable Set.Set where+  -- TODO: more efficient implementation+  ctraverse f =+      fmap Set.fromList+    . traverse f+    . Set.toList+  {-# INLINE [1] ctraverse #-}++instance CFoldable HS.HashSet where+  cfoldMap = ofoldMap+  {-# INLINE [1] cfoldMap #-}+  cfoldr = HS.foldr+  {-# INLINE [1] cfoldr #-}+  cfoldl' = HS.foldl'+  {-# INLINE [1] cfoldl' #-}+  celem = HS.member+  {-# INLINE [1] celem #-}+  cbasicToList = HS.toList+  {-# INLINE cbasicToList #-}++instance CTraversable HS.HashSet where+  -- TODO: more efficient implementation+  ctraverse f =+      fmap HS.fromList+    . traverse f+    . HS.toList+  {-# INLINE [1] ctraverse #-}++{-# RULES+"celem/IntSet"+  celem = coerce+    @(Int -> IS.IntSet -> Bool)+    @(Int -> WrapMono IS.IntSet Int -> Bool)+    IS.member+"cnotElem/IntSet"+  cnotElem = coerce+    @(Int -> IS.IntSet -> Bool)+    @(Int -> WrapMono IS.IntSet Int -> Bool)+    IS.notMember+"cmaximum/IntSet"+  cmaximum = coerce @_ @(WrapMono IS.IntSet Int -> Int)+    IS.findMax+"cminimum/IntSet"+  cminimum = coerce @(IS.IntSet -> Int) @(WrapMono IS.IntSet Int -> Int)+    IS.findMin+  #-}++instance MonoFoldable mono => CFoldable (WrapMono mono) where+  cfoldMap = ofoldMap+  {-# INLINE [1] cfoldMap #-}+  cfold = ofold+  {-# INLINE [1] cfold #-}+  cfoldr = ofoldr+  {-# INLINE [1] cfoldr #-}+  cfoldl' = ofoldl'+  {-# INLINE [1] cfoldl' #-}+  cfoldlM = ofoldlM+  {-# INLINE [1] cfoldlM #-}+  cbasicToList = otoList+  {-# INLINE cbasicToList #-}+  cfoldr1 = ofoldr1Ex+  {-# INLINE [1] cfoldr1 #-}+  cnull = onull+  {-# INLINE [1] cnull #-}+  clength = olength+  {-# INLINE [1] clength #-}+  cany = oany+  {-# INLINE [1] cany #-}+  call = oall+  {-# INLINE [1] call #-}+  celem = oelem+  {-# INLINE [1] celem #-}+  cnotElem = onotElem+  {-# INLINE [1] cnotElem #-}+  cminimum = minimumEx+  {-# INLINE [1] cminimum #-}+  cmaximum = maximumEx+  {-# INLINE [1] cmaximum #-}+  csum = osum+  {-# INLINE [1] csum #-}+  cproduct = oproduct+  {-# INLINE [1] cproduct #-}+  ctraverse_ = otraverse_+  {-# INLINE [1] ctraverse_ #-}++instance MonoTraversable mono => CTraversable (WrapMono mono) where+  ctraverse = \f -> fmap WrapMono . otraverse f . unwrapMono++instance CFoldable V.Vector where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap = foldMap+  {-# INLINE [1] cfoldr #-}+  cfoldr = V.foldr+  {-# INLINE [1] cfoldr' #-}+  cfoldr' = V.foldr'+  {-# INLINE [1] cfoldl #-}+  cfoldl = V.foldl+  {-# INLINE [1] cfoldl' #-}+  cfoldl' = V.foldl'+  {-# INLINE cfoldlM #-}+  cfoldlM = V.foldM+  {-# INLINE cfoldlM' #-}+  cfoldlM' = V.foldM'+  {-# INLINE [1] cindex #-}+  cindex = (V.!)+  {-# INLINE [1] celem #-}+  celem = V.elem+  {-# INLINE [1] cnotElem #-}+  cnotElem = V.notElem+  {-# INLINE [1] cany #-}+  cany = V.any+  {-# INLINE [1] call #-}+  call = V.all+  {-# INLINE [1] cfoldl1 #-}+  cfoldl1 = V.foldl1+  {-# INLINE [1] cfoldr1 #-}+  cfoldr1 = V.foldr1+  {-# INLINE [1] csum #-}+  csum = V.sum+  {-# INLINE [1] cproduct #-}+  cproduct = V.product+  {-# INLINE [1] cmaximum #-}+  cmaximum = V.maximum+  {-# INLINE [1] cminimum #-}+  cminimum = V.minimum+  {-# INLINE cbasicToList #-}+  cbasicToList = V.toList+  {-# INLINE [1] clast #-}+  clast = V.last+  {-# INLINE [1] chead #-}+  chead = V.head+  {-# INLINE [1] cfind #-}+  cfind = V.find+  {-# INLINE [1] cfindIndex #-}+  cfindIndex = V.findIndex+  {-# INLINE [1] cfindIndices #-}+  cfindIndices = fmap V.toList . V.findIndices+  {-# INLINE [1] celemIndex #-}+  celemIndex = V.elemIndex+  {-# INLINE [1] celemIndices #-}+  celemIndices = fmap V.toList . V.elemIndices++instance CFoldable U.Vector where+  {-# INLINE [1] cfoldMap #-}+  cfoldMap = ofoldMap+  {-# INLINE [1] cfoldr #-}+  cfoldr = U.foldr+  {-# INLINE [1] cfoldr' #-}+  cfoldr' = U.foldr'+  {-# INLINE [1] cfoldl #-}+  cfoldl = U.foldl+  {-# INLINE [1] cfoldl' #-}+  cfoldl' = U.foldl'+  {-# INLINE cfoldlM #-}+  cfoldlM = U.foldM+  {-# INLINE cfoldlM' #-}+  cfoldlM' = U.foldM'+  {-# INLINE [1] cindex #-}+  cindex = (U.!)+  {-# INLINE [1] celem #-}+  celem = U.elem+  {-# INLINE [1] cnotElem #-}+  cnotElem = U.notElem+  {-# INLINE [1] cany #-}+  cany = U.any+  {-# INLINE [1] call #-}+  call = U.all+  {-# INLINE [1] cfoldl1 #-}+  cfoldl1 = U.foldl1+  {-# INLINE [1] cfoldr1 #-}+  cfoldr1 = U.foldr1+  {-# INLINE [1] csum #-}+  csum = U.sum+  {-# INLINE [1] cproduct #-}+  cproduct = U.product+  {-# INLINE [1] cmaximum #-}+  cmaximum = U.maximum+  {-# INLINE [1] cminimum #-}+  cminimum = U.minimum+  {-# INLINE cbasicToList #-}+  cbasicToList = U.toList+  {-# INLINE [1] clast #-}+  clast = U.last+  {-# INLINE [1] chead #-}+  chead = U.head+  {-# INLINE [1] cfind #-}+  cfind = U.find+  {-# INLINE [1] cfindIndex #-}+  cfindIndex = U.findIndex+  {-# INLINE [1] cfindIndices #-}+  cfindIndices = fmap U.toList . U.findIndices+  {-# INLINE [1] celemIndex #-}+  celemIndex = U.elemIndex+  {-# INLINE [1] celemIndices #-}+  celemIndices = fmap U.toList . U.elemIndices++instance CFoldable S.Vector where+  {-# INLINE [1] cfoldr #-}+  cfoldr = S.foldr+  {-# INLINE [1] cfoldr' #-}+  cfoldr' = S.foldr'+  {-# INLINE [1] cfoldl #-}+  cfoldl = S.foldl+  {-# INLINE [1] cfoldl' #-}+  cfoldl' = S.foldl'+  {-# INLINE cfoldlM #-}+  cfoldlM = S.foldM+  {-# INLINE cfoldlM' #-}+  cfoldlM' = S.foldM'+  {-# INLINE [1] cindex #-}+  cindex = (S.!)+  {-# INLINE [1] celem #-}+  celem = S.elem+  {-# INLINE [1] cnotElem #-}+  cnotElem = S.notElem+  {-# INLINE [1] cany #-}+  cany = S.any+  {-# INLINE [1] call #-}+  call = S.all+  {-# INLINE [1] cfoldl1 #-}+  cfoldl1 = S.foldl1+  {-# INLINE [1] cfoldr1 #-}+  cfoldr1 = S.foldr1+  {-# INLINE [1] csum #-}+  csum = S.sum+  {-# INLINE [1] cproduct #-}+  cproduct = S.product+  {-# INLINE [1] cmaximum #-}+  cmaximum = S.maximum+  {-# INLINE [1] cminimum #-}+  cminimum = S.minimum+  {-# INLINE cbasicToList #-}+  cbasicToList = S.toList+  {-# INLINE [1] clast #-}+  clast = S.last+  {-# INLINE [1] chead #-}+  chead = S.head+  {-# INLINE [1] cfind #-}+  cfind = S.find+  {-# INLINE [1] cfindIndex #-}+  cfindIndex = S.findIndex+  {-# INLINE [1] cfindIndices #-}+  cfindIndices = fmap S.toList . S.findIndices+  {-# INLINE [1] celemIndex #-}+  celemIndex = S.elemIndex+  {-# INLINE [1] celemIndices #-}+  celemIndices = fmap S.toList . S.elemIndices++instance CFoldable P.Vector where+  {-# INLINE [1] cfoldr #-}+  cfoldr = P.foldr+  {-# INLINE [1] cfoldr' #-}+  cfoldr' = P.foldr'+  {-# INLINE [1] cfoldl #-}+  cfoldl = P.foldl+  {-# INLINE [1] cfoldl' #-}+  cfoldl' = P.foldl'+  {-# INLINE cfoldlM #-}+  cfoldlM = P.foldM+  {-# INLINE cfoldlM' #-}+  cfoldlM' = P.foldM'+  {-# INLINE [1] cindex #-}+  cindex = (P.!)+  {-# INLINE [1] celem #-}+  celem = P.elem+  {-# INLINE [1] cnotElem #-}+  cnotElem = P.notElem+  {-# INLINE [1] cany #-}+  cany = P.any+  {-# INLINE [1] call #-}+  call = P.all+  {-# INLINE [1] cfoldl1 #-}+  cfoldl1 = P.foldl1+  {-# INLINE [1] cfoldr1 #-}+  cfoldr1 = P.foldr1+  {-# INLINE [1] csum #-}+  csum = P.sum+  {-# INLINE [1] cproduct #-}+  cproduct = P.product+  {-# INLINE [1] cmaximum #-}+  cmaximum = P.maximum+  {-# INLINE [1] cminimum #-}+  cminimum = P.minimum+  {-# INLINE cbasicToList #-}+  cbasicToList = P.toList+  {-# INLINE [1] clast #-}+  clast = P.last+  {-# INLINE [1] chead #-}+  chead = P.head+  {-# INLINE [1] cfind #-}+  cfind = P.find+  {-# INLINE [1] cfindIndex #-}+  cfindIndex = P.findIndex+  {-# INLINE [1] cfindIndices #-}+  cfindIndices = fmap P.toList . P.findIndices+  {-# INLINE [1] celemIndex #-}+  celemIndex = P.elemIndex+  {-# INLINE [1] celemIndices #-}+  celemIndices = fmap P.toList . P.elemIndices++instance CTraversable V.Vector where+  ctraverse = traverse+  {-# INLINE [1] ctraverse #-}++instance CTraversable U.Vector where+  ctraverse = \f -> fmap S.convert . traverse f . U.convert @_ @_ @V.Vector+  {-# INLINE [1] ctraverse #-}++instance CTraversable S.Vector where+  ctraverse = \f -> fmap S.convert . traverse f . U.convert @_ @_ @V.Vector+  {-# INLINE [1] ctraverse #-}++instance CTraversable P.Vector where+  ctraverse = \f -> fmap P.convert . traverse f . U.convert @_ @_ @V.Vector+  {-# INLINE [1] ctraverse #-}++{-# RULES+"cindex/IsSequence" forall (xs :: (MT.Index mono ~ Int, IsSequence mono) => WrapMono mono b).+  cindex xs = withMonoCoercible (coerce @(mono -> Int -> Element mono) indexEx xs)+  #-}++{-# RULES+"cfromList/ctoList" [~1]+  cfromList . ctoList = id+"cfromList/ctoList" [~1] forall xs.+  cfromList (ctoList xs) = xs+  #-}++{-# RULES+"ctoList/cfromList" [~1]+  ctoList . cfromList = id+"ctoList/cfromList" forall xs.+  ctoList (cfromList xs) = xs+  #-}+-- | Free monoid functor from fullsubcategory.+--   It must be a pointed foldable functor with the property+--   that for any 'Monoid' @w@ and @f :: a -> w@,+--   @'cfoldMap' f@ must be a monoid homomorphism and the following+--   must be hold:+--+--    @+--       'cfoldMap' f . 'cpure' == f+--    @+--+--   Hence, @'Set's@ cannot be a free monoid functor;+class (CFunctor f, forall x. Dom f x => Monoid (f x), CPointed f, CFoldable f)+  => CFreeMonoid f where+  cbasicFromList :: Dom f a => [a] -> f a+  cbasicFromList = foldr ((<>) . cpure) mempty+  {-# INLINE cbasicFromList #-}++  ccons :: Dom f a => a -> f a -> f a+  {-# INLINE [1] ccons #-}+  ccons = (<>) . cpure++  csnoc :: Dom f a => f a -> a -> f a+  {-# INLINE [1] csnoc #-}+  csnoc = (. cpure) . (<>)++  {- |+    The 'cfromListN' function takes the input list's length as a hint. Its behaviour should be equivalent to 'cfromList'. The hint can be used to construct the structure l more efficiently compared to 'cfromList'.+    If the given hint does not equal to the input list's length the behaviour of fromListN is not specified.+  -}+  cfromListN :: Dom f a => Int -> [a] -> f a+  cfromListN = const cfromList+  {-# INLINE [1] cfromListN #-}++  ctake :: Dom f a => Int -> f a -> f a+  {-# INLINE [1] ctake #-}+  ctake n = cfromList . take n . ctoList++  cdrop :: Dom f a => Int -> f a -> f a+  {-# INLINE [1] cdrop #-}+  cdrop n = cfromList . drop n . ctoList++  cinit :: Dom f a => f a -> f a+  {-# INLINE [1] cinit #-}+  cinit = cfromList . init . ctoList++  ctail :: Dom f a => f a -> f a+  ctail = cfromList . tail . ctoList++  csplitAt :: Dom f a => Int -> f a -> (f a, f a)+  {-# INLINE [1] csplitAt #-}+  csplitAt n = (\(a, b) -> (cfromList a, cfromList b)) . splitAt n . ctoList++  creplicate :: Dom f a => Int -> a -> f a+  {-# INLINE [1] creplicate #-}+  creplicate n = cfromList . replicate n++  cgenerate :: Dom f a => Int -> (Int -> a) -> f a+  {-# INLINE [1] cgenerate #-}+  cgenerate = \n f ->+    cfromList [f i | i <- [0.. n - 1]]++  cgenerateM :: (Dom f a, Monad m) => Int -> (Int -> m a) -> m (f a)+  {-# INLINE [1] cgenerateM #-}+  cgenerateM = \n f ->+    cfromList <$> mapM f [0..n-1]++  cgenerateA :: (Dom f a, Applicative g) => Int -> (Int -> g a) -> g (f a)+  {-# INLINE [1] cgenerateA #-}+  cgenerateA = \n f ->+    cfromList <$> traverse f [0..n-1]++  cuncons :: Dom f a => f a -> Maybe (a, f a)+  {-# INLINE [1] cuncons #-}+  cuncons = fmap (second cfromList) . uncons . ctoList++  cunsnoc :: Dom f a => f a -> Maybe (f a, a)+  {-# INLINE [1] cunsnoc #-}+  cunsnoc = fmap (first cfromList) . MT.unsnoc . ctoList++  creverse :: Dom f a => f a -> f a+  {-# INLINE [1] creverse #-}+  creverse = cfromList . reverse . ctoList++  cintersperse :: Dom f a => a -> f a -> f a+  cintersperse = \a -> cfromList . intersperse a . ctoList++  cnub :: (Dom f a, Eq a) => f a -> f a+  {-# INLINE [1] cnub #-}+  cnub = cfromList . nub . ctoList++  cnubOrd :: (Dom f a, Ord a) => f a -> f a+  {-# INLINE [1] cnubOrd #-}+  cnubOrd = cfromList . L.foldOver cfolded L.nub++  csort :: (Dom f a, Ord a) => f a -> f a+  {-# INLINE [1] csort #-}+  csort = cfromList . List.sort . ctoList++  csortBy :: (Dom f a) => (a -> a -> Ordering) -> f a -> f a+  {-# INLINE [1] csortBy #-}+  csortBy = \f -> cfromList . List.sortBy f . ctoList++  cinsert :: (Dom f a, Ord a) => a -> f a -> f a+  {-# INLINE [1] cinsert #-}+  cinsert = \a -> cfromList . List.insert a . ctoList++  cinsertBy :: (Dom f a) => (a -> a -> Ordering) -> a -> f a -> f a+  {-# INLINE [1] cinsertBy #-}+  cinsertBy = \f a -> cfromList . List.insertBy f a . ctoList++  ctakeWhile :: Dom f a => (a -> Bool) -> f a -> f a+  {-# INLINE [1] ctakeWhile #-}+  ctakeWhile = \f -> cfromList . takeWhile f . ctoList++  cdropWhile :: Dom f a => (a -> Bool) -> f a -> f a+  {-# INLINE [1] cdropWhile #-}+  cdropWhile = \f -> cfromList . dropWhile f . ctoList++  cspan :: Dom f a => (a -> Bool) -> f a -> (f a, f a)+  {-# INLINE [1] cspan #-}+  cspan = \f -> (cfromList *** cfromList) . span f . ctoList++  cbreak :: Dom f a => (a -> Bool) -> f a -> (f a, f a)+  {-# INLINE [1] cbreak #-}+  cbreak = \f -> (cfromList *** cfromList) . break f . ctoList++  cfilter :: Dom f a => (a -> Bool) -> f a -> f a+  {-# INLINE [1] cfilter #-}+  cfilter = \f -> cfromList . filter f . ctoList++  cpartition :: Dom f a => (a -> Bool) -> f a -> (f a, f a)+  {-# INLINE [1] cpartition #-}+  cpartition = \f -> (cfromList *** cfromList) . List.partition f . ctoList++  -- TODO: more ListLike equivalent functions here++instance CFreeMonoid [] where+  cbasicFromList = id+  {-# INLINE cbasicFromList #-}+  cfromListN = take+  {-# INLINE [1] cfromListN #-}+  ccons = (:)+  {-# INLINE [1] ccons #-}+  csnoc = \xs x -> xs ++ [x]+  {-# INLINE [1] csnoc #-}+  ctake = take+  {-# INLINE [1] ctake #-}+  cdrop = drop+  {-# INLINE [1] cdrop #-}+  cinit = init+  {-# INLINE [1] cinit #-}+  ctail = tail+  {-# INLINE [1] ctail #-}+  csplitAt = splitAt+  {-# INLINE [1] csplitAt #-}+  creplicate = replicate+  {-# INLINE [1] creplicate #-}+  cgenerateM = \n f -> mapM f [0..n-1]+  {-# INLINE [1] cgenerateM #-}+  cgenerateA = \n f -> traverse f [0..n-1]+  {-# INLINE [1] cgenerateA #-}+  cuncons = uncons+  {-# INLINE [1] cuncons #-}+  cunsnoc = MT.unsnoc+  {-# INLINE [1] cunsnoc #-}+  creverse = reverse+  {-# INLINE [1] creverse #-}+  cintersperse = intersperse+  {-# INLINE [1] cintersperse #-}+  cnub = cnub+  {-# INLINE [1] cnub #-}+  csort = List.sort+  {-# INLINE [1] csort #-}+  csortBy = List.sortBy+  {-# INLINE [1] csortBy #-}+  ctakeWhile = takeWhile+  {-# INLINE [1] ctakeWhile #-}+  cdropWhile = dropWhile+  {-# INLINE [1] cdropWhile #-}+  cspan = span+  {-# INLINE [1] cspan #-}+  cbreak = break+  {-# INLINE [1] cbreak #-}+  cfilter = filter+  {-# INLINE [1] cfilter #-}+  cpartition = List.partition+  {-# INLINE [1] cpartition #-}++fmap concat $ forM+  [''V.Vector, ''U.Vector, ''S.Vector, ''P.Vector]+  $ \vecTy@(Name _ (NameG _ pkg modl0@(ModName mn))) ->+    let modl = maybe modl0 (ModName . T.unpack)+          $ T.stripSuffix ".Base" $ T.pack mn+        modFun fun = varE $+          Name (OccName fun) (NameG VarName pkg modl)+    in [d|+    instance CFreeMonoid $(conT vecTy) where+      cbasicFromList = $(modFun "fromList")+      {-# INLINE cbasicFromList #-}+      cfromListN = $(modFun "fromListN")+      {-# INLINE [1] cfromListN #-}+      ccons = $(modFun "cons")+      {-# INLINE [1] ccons #-}+      csnoc = $(modFun "snoc")+      {-# INLINE [1] csnoc #-}+      ctake = $(modFun "take")+      {-# INLINE [1] ctake #-}+      cdrop = $(modFun "drop")+      {-# INLINE [1] cdrop #-}+      cinit = $(modFun "init")+      {-# INLINE [1] cinit #-}+      ctail = $(modFun "tail")+      {-# INLINE [1] ctail #-}+      csplitAt = $(modFun "splitAt")+      {-# INLINE [1] csplitAt #-}+      creplicate = $(modFun "replicate")+      {-# INLINE [1] creplicate #-}+      cgenerate = $(modFun "generate")+      {-# INLINE [1] cgenerate #-}+      cgenerateM = $(modFun "generateM")+      {-# INLINE [1] cgenerateM #-}+      cgenerateA = \n f ->+        fmap VB.build+        $ getAp $ foldMap (Ap . fmap VB.singleton . f) [0..n-1]+      {-# INLINE [1] cgenerateA #-}+      cuncons = \xs ->+        if $(modFun "null") xs+        then Nothing+        else Just ($(modFun "head") xs, $(modFun "tail") xs)+      {-# INLINE [1] cuncons #-}+      cunsnoc = \xs ->+        if $(modFun "null") xs+        then Nothing+        else Just ($(modFun "init") xs, $(modFun "last") xs)+      {-# INLINE [1] cunsnoc #-}+      creverse = $(modFun "reverse")+      {-# INLINE [1] creverse #-}+      cnubOrd = $(modFun "uniq") . $(modFun "modify") AI.sort+      {-# INLINE cnubOrd #-}+      csort = $(modFun "modify") AI.sort+      {-# INLINE [1] csort #-}+      csortBy = \f -> $(modFun "modify") $ AI.sortBy f+      {-# INLINE [1] csortBy #-}+      ctakeWhile = $(modFun "takeWhile")+      {-# INLINE [1] ctakeWhile #-}+      cdropWhile = $(modFun "dropWhile")+      {-# INLINE [1] cdropWhile #-}+      cspan = $(modFun "span")+      {-# INLINE [1] cspan #-}+      cbreak = $(modFun "break")+      {-# INLINE [1] cbreak #-}+      cfilter = $(modFun "filter")+      {-# INLINE [1] cfilter #-}+      cpartition = $(modFun "partition")+      {-# INLINE [1] cpartition #-}+    |]++instance CFreeMonoid PA.PrimArray where+  cbasicFromList = PA.primArrayFromList+  {-# INLINE cbasicFromList #-}+  cfromListN = PA.primArrayFromListN+  {-# INLINE [1] cfromListN #-}+  cgenerate = PA.generatePrimArray+  {-# INLINE [1] cgenerate #-}+  cgenerateM = PA.generatePrimArrayA+  {-# INLINE [1] cgenerateM #-}+  cgenerateA = PA.generatePrimArrayA+  {-# INLINE [1] cgenerateA #-}+  cfilter = PA.filterPrimArray+  {-# INLINE [1] cfilter #-}+  creplicate = PA.replicatePrimArray+  {-# INLINE [1] creplicate #-}++instance CFreeMonoid SA.SmallArray where+  cbasicFromList = SA.smallArrayFromList+  {-# INLINE cbasicFromList #-}+  cfromListN = SA.smallArrayFromListN+  {-# INLINE [1] cfromListN #-}++instance CFreeMonoid A.Array where+  cbasicFromList = A.fromList+  {-# INLINE cbasicFromList #-}+  cfromListN = A.fromListN+  {-# INLINE [1] cfromListN #-}+instance CFreeMonoid Seq.Seq where+  cbasicFromList = Seq.fromList+  {-# INLINE cbasicFromList #-}+  cfromListN = GHC.fromListN+  {-# INLINE [1] cfromListN #-}++instance MT.IsSequence mono+      => CFreeMonoid (WrapMono mono) where+  cbasicFromList = coerce $ MT.fromList @mono+  {-# INLINE cbasicFromList #-}+  cfromListN = \n -> coerce $ MT.take (fromIntegral n) . MT.fromList @mono+  {-# INLINE [1] cfromListN #-}+  ctake = coerce . MT.take @mono . fromIntegral+  {-# INLINE [1] ctake #-}+  cdrop = coerce . MT.drop @mono . fromIntegral+  {-# INLINE [1] cdrop #-}+  ccons = coerce $ MT.cons @mono+  {-# INLINE ccons #-}+  csnoc = coerce $ MT.snoc @mono+  {-# INLINE [1] csnoc #-}+  cuncons = coerce $ MT.uncons @mono+  {-# INLINE [1] cuncons #-}+  cunsnoc = coerce $ MT.unsnoc @mono+  {-# INLINE [1] cunsnoc #-}+  ctail = coerce $ MT.tailEx @mono+  {-# INLINE [1] ctail #-}+  cinit = coerce $ MT.initEx @mono+  {-# INLINE [1] cinit #-}+  csplitAt = coerce $ \(n :: Int) ->+      MT.splitAt @mono (fromIntegral n :: MT.Index mono)+  {-# INLINE [1] csplitAt #-}+  creplicate = coerce $ \(n :: Int) ->+      MT.replicate @mono (fromIntegral n :: MT.Index mono)+  {-# INLINE [1] creplicate #-}+  creverse = coerce $ MT.reverse @mono+  {-# INLINE [1] creverse #-}+  cintersperse = coerce $ MT.intersperse @mono+  {-# INLINE [1] cintersperse #-}+  csort = coerce $ MT.sort @mono+  {-# INLINE [1] csort #-}+  csortBy = coerce $ MT.sortBy @mono+  {-# INLINE [1] csortBy #-}+  ctakeWhile = coerce $ MT.takeWhile @mono+  {-# INLINE [1] ctakeWhile #-}+  cdropWhile = coerce $ MT.dropWhile @mono+  {-# INLINE [1] cdropWhile #-}+  cbreak = coerce $ MT.break @mono+  {-# INLINE [1] cbreak #-}+  cspan = coerce $ MT.span @mono+  {-# INLINE [1] cspan #-}+  cfilter = coerce $ MT.filter @mono+  {-# INLINE [1] cfilter #-}+  cpartition = coerce $ MT.partition @mono+  {-# INLINE [1] cpartition #-}++cctraverseFreeMonoid+  ::  ( CFreeMonoid t, CApplicative f, CPointed f,+        Dom t a, Dom f (t b), Dom f b, Dom t b,+        Dom f (t b, t b)+      )+  => (a -> f b) -> t a -> f (t b)+cctraverseFreeMonoid f =+  runCApp . cfoldMap (CApp . cmap cpure . f)++cctraverseZipFreeMonoid+  :: ( CFreeMonoid t, CRepeat f,+        Dom t a, Dom f (t b), Dom f b, Dom t b,+        Dom f (t b, t b)+      )+  => (a -> f b) -> t a -> f (t b)+cctraverseZipFreeMonoid f =+  runCZippy . cfoldMap (CZippy . cmap cpure . f)++-- | Lifts 'CFoldable' along given function.+--+--  @+--    cfolding :: (CFoldable t, Dom t a) => (s -> t a) -> Fold s a+--  @+cfolding+  :: (CFoldable t, Dom t a, Contravariant f, Applicative f)+  => (s -> t a)+  -> (a -> f a) -> s -> f s+{-# INLINE cfolding #-}+cfolding = \sfa agb -> phantom . ctraverse_ agb . sfa
+ src/Control/Subcategory/Functor.hs view
@@ -0,0 +1,375 @@+{-# LANGUAGE CPP, DerivingVia, GADTs, InstanceSigs, KindSignatures    #-}+{-# LANGUAGE PatternSynonyms, RankNTypes, RoleAnnotations             #-}+{-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TemplateHaskell #-}+{-# LANGUAGE TypeApplications, TypeFamilies, TypeOperators            #-}+{-# LANGUAGE UndecidableSuperClasses                                  #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Control.Subcategory.Functor+  ( Constrained(..), Dom(), CFunctor (..),+    (<$:>),+    defaultCmapConst,+    WrapFunctor (..),+    WrapMono (WrapMono, unwrapMono),+    coerceToMono, withMonoCoercible,+  )+where+import qualified Control.Applicative                  as App+import           Control.Arrow                        (Arrow, ArrowMonad)+import           Control.Exception                    (Handler)+import qualified Control.Monad.ST.Lazy                as LST+import qualified Control.Monad.ST.Strict              as SST+import           Control.Subcategory.Wrapper.Internal+import           Data.Coerce+import           Data.Complex                         (Complex)+import qualified Data.Functor.Compose                 as SOP+import           Data.Functor.Const                   (Const)+import           Data.Functor.Identity                (Identity)+import qualified Data.Functor.Product                 as SOP+import qualified Data.Functor.Sum                     as SOP+import           Data.Hashable                        (Hashable)+import qualified Data.HashMap.Strict                  as HM+import qualified Data.HashSet                         as HS+import qualified Data.IntMap                          as IM+import           Data.Kind                            (Constraint, Type)+import           Data.List.NonEmpty                   (NonEmpty)+import qualified Data.Map                             as Map+import qualified Data.Monoid                          as Mon+import           Data.MonoTraversable                 (Element,+                                                       MonoFunctor (..))+#if MIN_VERSION_mono_traversable(1,0,14)+import Data.MonoTraversable (WrappedMono)+#endif++import qualified Data.IntSet                     as IS+import           Data.Ord                        (Down (..))+import qualified Data.Primitive.Array            as A+import qualified Data.Primitive.PrimArray        as PA+import qualified Data.Primitive.SmallArray       as SA+import           Data.Proxy                      (Proxy)+import qualified Data.Semigroup                  as Sem+import qualified Data.Sequence                   as Seq+import qualified Data.Set                        as Set+import qualified Data.Tree                       as Tree+import qualified Data.Vector                     as V+import qualified Data.Vector.Primitive           as P+import qualified Data.Vector.Storable            as S+import qualified Data.Vector.Unboxed             as U+import           Foreign.Ptr                     (Ptr)+import           GHC.Conc                        (STM)+import           GHC.Generics                    ((:*:) (..), (:+:) (..),+                                                  (:.:) (..), K1, M1, Par1,+                                                  Rec1, U1, URec, V1)+import qualified System.Console.GetOpt           as GetOpt+import           Text.ParserCombinators.ReadP    (ReadP)+import           Text.ParserCombinators.ReadPrec (ReadPrec)++infixl 4 <$:++class Constrained (f :: Type -> Type) where+  type Dom f (a :: Type) :: Constraint+  type Dom f a = ()++class Constrained f => CFunctor f where+  cmap :: (Dom f a, Dom f b) => (a -> b) -> f a -> f b+  default cmap :: Functor f => (a -> b) -> f a -> f b+  cmap = fmap+  {-# INLINE cmap #-}+  (<$:) :: (Dom f a, Dom f b) => a -> f b -> f a+  (<$:) = cmap . const+  {-# INLINE (<$:) #-}++defaultCmapConst :: (CFunctor f, Dom f a, Dom f b) => a -> f b -> f a+defaultCmapConst = cmap . const+{-# INLINE defaultCmapConst #-}++instance Constrained (WrapFunctor f) where+  type Dom (WrapFunctor f) a = ()++instance Functor f => CFunctor (WrapFunctor f) where+  cmap :: (a -> b) -> WrapFunctor f a -> WrapFunctor f b+  cmap = fmap+  {-# INLINE cmap #-}+  (<$:) :: a -> WrapFunctor f b -> WrapFunctor f a+  (<$:) = (<$)+  {-# INLINE (<$:) #-}++instance Constrained []+instance CFunctor []+instance Constrained Maybe+instance CFunctor Maybe+instance Constrained IO+instance CFunctor IO+instance Constrained Par1+instance CFunctor Par1+instance Constrained NonEmpty+instance CFunctor NonEmpty+instance Constrained ReadP+instance CFunctor ReadP+instance Constrained ReadPrec+instance CFunctor ReadPrec+++instance Constrained Down+instance CFunctor Down+instance Constrained Mon.Product+instance CFunctor Mon.Product++instance Constrained Mon.Sum+instance CFunctor Mon.Sum+instance Constrained Mon.Dual+instance CFunctor Mon.Dual++instance Constrained Mon.Last+instance CFunctor Mon.Last+instance Constrained Mon.First+instance CFunctor Mon.First++instance Constrained STM+instance CFunctor STM+instance Constrained Handler+instance CFunctor Handler++instance Constrained Identity+instance CFunctor Identity+instance Constrained App.ZipList+instance CFunctor App.ZipList+instance Constrained GetOpt.ArgDescr+instance CFunctor GetOpt.ArgDescr+instance Constrained GetOpt.OptDescr+instance CFunctor GetOpt.OptDescr+instance Constrained GetOpt.ArgOrder+instance CFunctor GetOpt.ArgOrder+instance Constrained Sem.Option+instance CFunctor Sem.Option++instance Constrained Sem.Last+instance CFunctor Sem.Last+instance Constrained Sem.First+instance CFunctor Sem.First++instance Constrained Sem.Max+instance CFunctor Sem.Max+instance Constrained Sem.Min+instance CFunctor Sem.Min++instance Constrained Complex+instance CFunctor Complex+instance Constrained (Either a)+instance CFunctor (Either a)++instance Constrained V1+instance CFunctor V1+instance Constrained U1+instance CFunctor U1++instance Constrained ((,) a)+instance CFunctor ((,) a)+instance Constrained (SST.ST s)+instance CFunctor (SST.ST s)++instance Constrained (LST.ST s)+instance CFunctor (LST.ST s)+instance Constrained Proxy+instance CFunctor Proxy++instance Constrained (ArrowMonad a)+instance Arrow a => CFunctor (ArrowMonad a)+instance Constrained (App.WrappedMonad m)+instance Monad m => CFunctor (App.WrappedMonad m)++instance Constrained (Sem.Arg a)+instance CFunctor (Sem.Arg a)+instance Constrained (Rec1 f)+instance Functor f => CFunctor (Rec1 f)++instance Constrained (URec Char)+instance CFunctor (URec Char)+instance Constrained (URec Double)+instance CFunctor (URec Double)++instance Constrained (URec Float)+instance CFunctor (URec Float)+instance Constrained (URec Int)+instance CFunctor (URec Int)++instance Constrained (URec Word)+instance CFunctor (URec Word)+instance Constrained (URec (Ptr ()))+instance CFunctor (URec (Ptr ()))++instance Constrained f => Constrained (Mon.Ap f) where+  type Dom (Mon.Ap f) a = Dom f a++deriving newtype instance CFunctor f => CFunctor (Mon.Ap f)++instance Constrained (Mon.Alt f) where+  type Dom (Mon.Alt f) a = Dom f a+deriving newtype instance CFunctor f => CFunctor (Mon.Alt f)++instance Constrained (Const m)+instance CFunctor (Const m)+instance Constrained (App.WrappedArrow a b)+instance Arrow a => CFunctor (App.WrappedArrow a b)++instance Constrained ((->) r)+instance CFunctor ((->) r)+instance Constrained (K1 i c)+instance CFunctor (K1 i c)++instance Constrained (f :+: g) where+  type Dom (f :+: g) a = (Dom f a, Dom g a)+instance (CFunctor f, CFunctor g) => CFunctor (f :+: g) where+  cmap f (L1 xs) = L1 $ cmap f xs+  cmap f (R1 xs) = R1 $ cmap f xs+  {-# INLINE [1] cmap #-}+instance Constrained (f :*: g) where+  type Dom (f :*: g) a = (Dom f a, Dom g a)+instance (CFunctor f, CFunctor g) => CFunctor (f :*: g) where+  cmap f (l :*: r) = cmap f l :*: cmap f r+  {-# INLINE cmap #-}++instance Constrained (f :.: (g :: Type -> Type)) where+  type Dom (f :.: g) a = (Dom f (g a), Dom g a)+instance (CFunctor f, CFunctor g) => CFunctor (f :.: g) where+  cmap f gfa = Comp1 $ cmap (cmap f) $ unComp1 gfa+  {-# INLINE cmap #-}+instance (Constrained f, Constrained g) => Constrained (SOP.Sum f g) where+  type Dom (SOP.Sum f g) a = (Dom f a, Dom g a)++instance (CFunctor f, CFunctor g) => CFunctor (SOP.Sum f g) where+  cmap f (SOP.InL a) = SOP.InL $ cmap f a+  cmap f (SOP.InR b) = SOP.InR $ cmap f b+  {-# INLINE cmap #-}++  (<$:) = defaultCmapConst+  {-# INLINE (<$:) #-}++instance (Constrained f, Constrained g) => Constrained (SOP.Product f g) where+  type Dom (SOP.Product f g) a = (Dom f a, Dom g a)++instance (CFunctor f, CFunctor g) => CFunctor (SOP.Product f g) where+  cmap f (SOP.Pair a b) = SOP.Pair (cmap f a) (cmap f b)+  {-# INLINE cmap #-}++  (<$:) = defaultCmapConst+  {-# INLINE (<$:) #-}++instance (Constrained (f ::Type -> Type), Constrained (g :: Type -> Type))+  => Constrained (SOP.Compose f g) where+  type Dom (SOP.Compose f g) a = (Dom g a, Dom f (g a))++instance (CFunctor f, CFunctor g) => CFunctor (SOP.Compose f g) where+  cmap f (SOP.Compose a) = SOP.Compose $ cmap (cmap f) a+  (<$:) = defaultCmapConst++  {-# INLINE (<$:) #-}++instance Constrained (M1 i c f)+instance Functor f => CFunctor (M1 i c f)++instance Constrained Seq.Seq+instance CFunctor Seq.Seq++#if MIN_VERSION_mono_traversable(1,0,14)+instance Constrained (WrappedMono mono) where+  type Dom (WrappedMono mono) a = a ~ Element mono++instance MonoFunctor IS.IntSet where+  omap = IS.map++instance MonoFunctor mono => CFunctor (WrappedMono mono) where+  cmap = omap+  (<$:) = omap . const+#endif++instance Constrained (WrapMono mono) where+  type Dom (WrapMono mono) b = b ~ Element mono++instance {-# OVERLAPPABLE #-} MonoFunctor a+      => CFunctor (WrapMono a) where+  cmap = coerce @((Element a -> Element a) -> a -> a) omap+  {-# INLINE [1] cmap #-}++  (<$:) = defaultCmapConst+  {-# INLINE [1] (<$:) #-}+++instance Constrained IM.IntMap+instance CFunctor IM.IntMap++instance Constrained (Map.Map k)+instance Ord k => CFunctor (Map.Map k)++instance Constrained Set.Set where+  type Dom Set.Set a = Ord a++instance CFunctor Set.Set where+  cmap = Set.map+  {-# INLINE [1] cmap #-}+  (<$:) = flip $ \s ->+    if Set.null s+    then const Set.empty else Set.singleton+  {-# INLINE [1] (<$:) #-}++instance Constrained HS.HashSet where+  type Dom HS.HashSet a = (Hashable a, Eq a)++instance CFunctor HS.HashSet where+  cmap :: (Hashable b, Eq b) => (a -> b) -> HS.HashSet a -> HS.HashSet b+  cmap = HS.map+  {-# INLINE [1] cmap #-}+  (<$:) = flip $ \s -> if HS.null s+    then const HS.empty else HS.singleton+  {-# INLINE (<$:) #-}++instance Constrained (HM.HashMap k)+instance CFunctor (HM.HashMap k)+instance Constrained Tree.Tree+instance CFunctor Tree.Tree+++infixl 4 <$:>+(<$:>) :: (CFunctor f, Dom f a, Dom f b) => (a -> b) -> f a -> f b+(<$:>) = cmap+{-# INLINE [1] (<$:>) #-}++instance Constrained V.Vector where+  type Dom V.Vector a = ()++instance CFunctor V.Vector where+  cmap = V.map+  {-# INLINE [1] cmap #-}++instance Constrained U.Vector where+  type Dom U.Vector a = U.Unbox a+instance CFunctor U.Vector where+  cmap = U.map+  {-# INLINE [1] cmap #-}+instance Constrained S.Vector where+  type Dom S.Vector a = S.Storable a+instance CFunctor S.Vector where+  cmap = S.map+  {-# INLINE [1] cmap #-}++instance Constrained P.Vector where+  type Dom P.Vector a = P.Prim a+instance CFunctor P.Vector where+  cmap = P.map+  {-# INLINE [1] cmap #-}++instance Constrained PA.PrimArray where+  type Dom PA.PrimArray a = P.Prim a++instance CFunctor PA.PrimArray where+  cmap = PA.mapPrimArray+  {-# INLINE [1] cmap #-}++deriving via WrapFunctor SA.SmallArray+  instance Constrained SA.SmallArray+deriving via WrapFunctor SA.SmallArray+  instance CFunctor SA.SmallArray++deriving via WrapFunctor A.Array+  instance Constrained A.Array+deriving via WrapFunctor A.Array+  instance CFunctor A.Array
+ src/Control/Subcategory/Pointed.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE DerivingVia, StandaloneDeriving, TypeOperators #-}+module Control.Subcategory.Pointed where+import Control.Subcategory.Functor++import qualified Control.Applicative             as App+import qualified Control.Monad.ST.Lazy           as LST+import qualified Control.Monad.ST.Strict         as SST+import qualified Data.Functor.Compose            as SOP+import           Data.Functor.Identity           (Identity)+import qualified Data.Functor.Product            as SOP+import qualified Data.HashSet                    as HS+import qualified Data.IntSet                     as IS+import           Data.List.NonEmpty              (NonEmpty)+import qualified Data.Monoid                     as Mon+import           Data.MonoTraversable            (MonoPointed, opoint)+import           Data.Ord                        (Down)+import qualified Data.Pointed                    as Pt+import qualified Data.Primitive.Array            as A+import qualified Data.Primitive.PrimArray        as PA+import qualified Data.Primitive.SmallArray       as SA+import           Data.Proxy                      (Proxy)+import qualified Data.Semigroup                  as Sem+import qualified Data.Sequence                   as Seq+import qualified Data.Set                        as Set+import qualified Data.Tree                       as Tree+import qualified Data.Vector                     as V+import qualified Data.Vector.Primitive           as P+import qualified Data.Vector.Storable            as S+import qualified Data.Vector.Unboxed             as U+import           GHC.Conc                        (STM)+import           GHC.Generics                    ((:*:) (..), (:.:) (..))+import           GHC.Generics                    (Par1, Rec1, U1)+import           Text.ParserCombinators.ReadP    (ReadP)+import           Text.ParserCombinators.ReadPrec (ReadPrec)++class Constrained f => CPointed f where+  cpure :: Dom f a => a -> f a+  default cpure :: App.Applicative f => a -> f a+  cpure = pure++instance (Functor f, Pt.Pointed f) => CPointed (WrapFunctor f) where+  cpure = Pt.point+  {-# INLINE cpure #-}++instance CPointed []+instance CPointed Maybe+instance CPointed IO+instance CPointed (SST.ST s)+instance CPointed (LST.ST s)+instance CPointed Par1+instance CPointed Sem.Min+instance CPointed Sem.Max+instance CPointed Mon.First+instance CPointed Mon.Last+instance CPointed Sem.First+instance CPointed Sem.Last+instance CPointed Sem.Option+instance CPointed NonEmpty+instance CPointed App.ZipList+instance CPointed Identity+instance CPointed STM+instance CPointed Sem.Dual+instance CPointed Sem.Sum+instance CPointed Sem.Product+instance CPointed Down+instance CPointed Tree.Tree+instance CPointed Seq.Seq+instance CPointed Set.Set where+  cpure = Set.singleton+  {-# INLINE cpure #-}+instance CPointed (Either a)+instance CPointed U1+instance CPointed Proxy+instance (Pt.Pointed f) => CPointed (Rec1 f) where+  cpure = Pt.point+  {-# INLINE cpure #-}+instance (Pt.Pointed p, Pt.Pointed q)+      => CPointed (p :*: q) where+  cpure a = (:*:) (Pt.point a) (Pt.point a)+  {-# INLINE cpure #-}+instance (Pt.Pointed p, Pt.Pointed q)+      => CPointed (p :.: q) where+  cpure a = Comp1 $ Pt.point $ Pt.point a+  {-# INLINE cpure #-}+instance (Constrained p, Constrained q, Pt.Pointed p, Pt.Pointed q)+      => CPointed (SOP.Compose p q) where+  cpure a = SOP.Compose $ Pt.point $ Pt.point a+  {-# INLINE cpure #-}+instance (CPointed p, CPointed q)+      => CPointed (SOP.Product p q) where+  cpure a = SOP.Pair (cpure a) (cpure a)+  {-# INLINE cpure #-}+instance CPointed ReadP+instance CPointed ReadPrec+instance CPointed (WrapMono IS.IntSet) where+  cpure = WrapMono . IS.singleton+  {-# INLINE cpure #-}+instance CPointed HS.HashSet where+  cpure = HS.singleton+  {-# INLINE cpure #-}++instance MonoPointed mono => CPointed (WrapMono mono) where+  cpure = opoint++instance CPointed V.Vector where+  cpure = V.singleton+  {-# INLINE [1] cpure #-}++instance CPointed U.Vector where+  cpure = U.singleton+  {-# INLINE [1] cpure #-}++instance CPointed S.Vector where+  cpure = S.singleton+  {-# INLINE [1] cpure #-}++instance CPointed P.Vector where+  cpure = P.singleton+  {-# INLINE [1] cpure #-}++instance CPointed PA.PrimArray where+  cpure = PA.replicatePrimArray 1+  {-# INLINE [1] cpure #-}++instance CPointed SA.SmallArray where+  cpure = SA.smallArrayFromListN 1 . pure+  {-# INLINE [1] cpure #-}++instance CPointed A.Array where+  cpure = A.fromListN 1 . pure+  {-# INLINE [1] cpure #-}
+ src/Control/Subcategory/RebindableSyntax.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE NoImplicitPrelude #-}+module Control.Subcategory.RebindableSyntax+  ( ifThenElse, Eq(..), Num(..)+  , (>>=), (>>), fromLabel, return+  , module Control.Arrow+  ) where+import Control.Subcategory.Applicative+import Control.Subcategory.Bind+import Control.Subcategory.Functor+import Control.Subcategory.Pointed++import Control.Arrow+import GHC.OverloadedLabels+import Prelude              (Bool (..), Eq (..), Num (..))++ifThenElse :: Bool -> a -> a -> a+ifThenElse True t _  = t+ifThenElse False _ f = f+{-# INLINE ifThenElse #-}++(>>=) :: (Dom m a, Dom m b, CBind m)+      => m a -> (a -> m b) -> m b+(>>=) = (>>-)+{-# INLINE (>>=) #-}++(>>) :: (Dom m a, Dom m b, CApplicative m)+      => m a -> m b -> m b+(>>) = (.>)+{-# INLINE (>>) #-}++return :: (Dom m a, CPointed m) => a -> m a+return = cpure+{-# INLINE return #-}
+ src/Control/Subcategory/Semialign.hs view
@@ -0,0 +1,302 @@+{-# LANGUAGE BangPatterns, CPP, DerivingStrategies, DerivingVia         #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, MultiWayIf, StandaloneDeriving #-}+{-# LANGUAGE TypeOperators                                              #-}+module Control.Subcategory.Semialign+  ( CSemialign(..), CAlign(..),+    csalign, cpadZip, cpadZipWith+  ) where+import           Control.Applicative                  (ZipList)+import           Control.Monad                        (forM_)+import           Control.Monad.ST.Strict              (runST)+import           Control.Subcategory.Functor+import           Control.Subcategory.Wrapper.Internal+import           Data.Bifunctor                       (Bifunctor (bimap))+import           Data.Coerce+import           Data.Containers+import           Data.Functor.Compose                 (Compose (..))+import           Data.Functor.Identity                (Identity)+import qualified Data.Functor.Product                 as SOP+import           Data.Hashable                        (Hashable)+import           Data.HashMap.Strict                  (HashMap)+import           Data.IntMap.Strict                   (IntMap)+import qualified Data.IntSet                          as IS+import           Data.List.NonEmpty                   (NonEmpty)+import           Data.Map                             (Map)+import           Data.MonoTraversable+import qualified Data.Primitive.Array                 as A+import qualified Data.Primitive.PrimArray             as PA+import qualified Data.Primitive.SmallArray            as SA+import           Data.Proxy                           (Proxy)+import           Data.Semialign+import           Data.Semigroup                       (Option (..))+import           Data.Sequence                        (Seq)+import qualified Data.Sequences                       as MT+import           Data.These                           (These (..), fromThese,+                                                       mergeThese)+import           Data.Tree                            (Tree)+import qualified Data.Vector                          as V+import qualified Data.Vector.Primitive                as P+import qualified Data.Vector.Storable                 as S+import qualified Data.Vector.Unboxed                  as U+import           GHC.Generics                         ((:*:) (..), (:.:) (..))++class CFunctor f => CSemialign f where+  {-# MINIMAL calignWith #-}+  calignWith+    :: (Dom f a, Dom f b, Dom f c)+    => (These a b -> c) -> f a -> f b -> f c+  calign+    :: (Dom f a, Dom f b, Dom f (These a b))+    => f a -> f b -> f (These a b)+  {-# INLINE [1] calign #-}+  calign = calignWith id++instance Semialign f => CSemialign (WrapFunctor f) where+  calignWith = alignWith+  {-# INLINE [1] calignWith #-}+  calign = align+  {-# INLINE [1] calign #-}++instance {-# OVERLAPPING #-}  CSemialign (WrapMono IS.IntSet) where+  calignWith f = withMonoCoercible @IS.IntSet $+    coerce @(IS.IntSet -> IS.IntSet -> IS.IntSet) $ \ l r ->+    let ints = l `IS.intersection` r+    in IS.unions+          [ IS.map (f . This) l+          , IS.map (f . That) r+          , IS.map (\x -> f $ These x x) ints+          ]+  {-# INLINE [1] calignWith #-}++class CSemialign f => CAlign f where+  cnil :: Dom f a => f a++instance Align f => CAlign (WrapFunctor f) where+  cnil = WrapFunctor nil+  {-# INLINE [1] cnil #-}++deriving via WrapFunctor [] instance CSemialign []+deriving via WrapFunctor [] instance CAlign []+deriving via WrapFunctor Maybe instance CSemialign Maybe+deriving via WrapFunctor Maybe instance CAlign Maybe+#if MIN_VERSION_semialign(1,1,0)+deriving via WrapFunctor Option instance CSemialign Option+deriving via WrapFunctor Option instance CAlign Option+#else+deriving newtype instance CSemialign Option+deriving newtype instance CAlign Option+#endif++deriving via WrapFunctor ZipList instance CSemialign ZipList+deriving via WrapFunctor ZipList instance CAlign ZipList+deriving via WrapFunctor Identity instance CSemialign Identity+deriving via WrapFunctor NonEmpty instance CSemialign NonEmpty+deriving via WrapFunctor IntMap instance CSemialign IntMap+deriving via WrapFunctor IntMap instance CAlign IntMap+deriving via WrapFunctor Tree instance CSemialign Tree+deriving via WrapFunctor Seq instance CSemialign Seq+deriving via WrapFunctor Seq instance CAlign Seq+deriving via WrapFunctor V.Vector instance CSemialign V.Vector+deriving via WrapFunctor V.Vector instance CAlign V.Vector+deriving via WrapFunctor Proxy instance CSemialign Proxy+deriving via WrapFunctor Proxy instance CAlign Proxy+deriving via WrapFunctor (Map k) instance Ord k => CSemialign (Map k)+deriving via WrapFunctor (Map k) instance Ord k => CAlign (Map k)+deriving via WrapFunctor (HashMap k)+  instance (Eq k, Hashable k) => CSemialign (HashMap k)+deriving via WrapFunctor (HashMap k)+  instance (Eq k, Hashable k) => CAlign (HashMap k)+deriving via WrapFunctor ((->) s) instance CSemialign ((->) s)++instance (CSemialign f, CSemialign g) => CSemialign (SOP.Product f g) where+  calign (SOP.Pair a b) (SOP.Pair c d) = SOP.Pair (calign a c) (calign b d)+  {-# INLINE [1] calign #-}+  calignWith f (SOP.Pair a b) (SOP.Pair c d) =+    SOP.Pair (calignWith f a c) (calignWith f b d)+  {-# INLINE [1] calignWith #-}++instance (CAlign f, CAlign g) => CAlign (SOP.Product f g) where+  cnil = SOP.Pair cnil cnil+  {-# INLINE [1] cnil #-}++instance (CSemialign f, CSemialign g) => CSemialign (f :*: g) where+  calign ((:*:) a b) ((:*:) c d) = (:*:) (calign a c) (calign b d)+  {-# INLINE [1] calign #-}+  calignWith f ((:*:) a b) ((:*:) c d) =+    (:*:) (calignWith f a c) (calignWith f b d)+  {-# INLINE [1] calignWith #-}++instance (CAlign f, CAlign g) => CAlign (f :*: g) where+  cnil = cnil :*: cnil+  {-# INLINE [1] cnil #-}++instance (CSemialign f, CSemialign g) => CSemialign (Compose f g) where+  calignWith f (Compose x) (Compose y) = Compose (calignWith g x y)+    where+      g (This ga)     = cmap (f . This) ga+      g (That gb)     = cmap (f . That) gb+      g (These ga gb) = calignWith f ga gb+  {-# INLINE [1] calignWith #-}++instance (CAlign f, CSemialign g) => CAlign (Compose f g) where+  cnil = Compose cnil+  {-# INLINE [1] cnil #-}++instance (CSemialign f, CSemialign g) => CSemialign ((:.:) f g) where+  calignWith f (Comp1 x) (Comp1 y) = Comp1 (calignWith g x y)+    where+      g (This ga)     = cmap (f . This) ga+      g (That gb)     = cmap (f . That) gb+      g (These ga gb) = calignWith f ga gb+  {-# INLINE [1] calignWith #-}++instance (CAlign f, CSemialign g) => CAlign ((:.:) f g) where+  cnil = Comp1 cnil+  {-# INLINE [1] cnil #-}++instance CSemialign U.Vector where+  calignWith = alignVectorWith+  {-# INLINE [1] calignWith #-}++instance CAlign U.Vector where+  cnil = U.empty+  {-# INLINE [1] cnil #-}++instance CSemialign S.Vector where+  calignWith = alignVectorWith+  {-# INLINE [1] calignWith #-}++instance CAlign S.Vector where+  cnil = S.empty+  {-# INLINE [1] cnil #-}++instance CSemialign P.Vector where+  calignWith = alignVectorWith+  {-# INLINE [1] calignWith #-}++instance CAlign P.Vector where+  cnil = P.empty+  {-# INLINE [1] cnil #-}++instance CSemialign SA.SmallArray where+  calignWith f l r = runST $ do+    let !lenL = length l+        !lenR = length r+        (isLftShort, thresh, len)+          | lenL < lenR = (True, lenL, lenR)+          | otherwise = (False, lenR, lenL)+    sa <- SA.newSmallArray len (error "Uninitialised element")+    forM_ [0..len-1] $ \n ->+      if  | n == len -> pure ()+          | n < thresh ->+            SA.writeSmallArray sa n+            $ f $ These+              (SA.indexSmallArray l n)+              (SA.indexSmallArray r n)+          | isLftShort ->+            SA.writeSmallArray sa n+            $ f $ That $ SA.indexSmallArray r n+          | otherwise ->+            SA.writeSmallArray sa n+            $ f $ This $ SA.indexSmallArray l n+    SA.unsafeFreezeSmallArray sa+  {-# INLINE [1] calignWith #-}++instance CAlign SA.SmallArray where+  cnil = SA.smallArrayFromListN 0 []+  {-# INLINE [1] cnil #-}++instance CSemialign A.Array where+  calignWith f l r = runST $ do+    let !lenL = length l+        !lenR = length r+        (isLftShort, thresh, len)+          | lenL < lenR = (True, lenL, lenR)+          | otherwise = (False, lenR, lenL)+    sa <- A.newArray len (error "Uninitialised element")+    forM_ [0..len-1] $ \n ->+      if  | n == len -> pure ()+          | n < thresh ->+            A.writeArray sa n+            $ f $ These+              (A.indexArray l n)+              (A.indexArray r n)+          | isLftShort ->+            A.writeArray sa n+            $ f $ That $ A.indexArray r n+          | otherwise ->+            A.writeArray sa n+            $ f $ This $ A.indexArray l n+    A.unsafeFreezeArray sa+  {-# INLINE [1] calignWith #-}++instance CAlign A.Array where+  cnil = A.fromListN 0 []+  {-# INLINE [1] cnil #-}++instance CSemialign PA.PrimArray where+  calignWith f l r = runST $ do+    let !lenL = PA.sizeofPrimArray l+        !lenR = PA.sizeofPrimArray r+        (isLftShort, thresh, len)+          | lenL < lenR = (True, lenL, lenR)+          | otherwise = (False, lenR, lenL)+    sa <- PA.newPrimArray len+    forM_ [0..len-1] $ \n ->+      if  | n == len -> pure ()+          | n < thresh ->+            PA.writePrimArray sa n+            $ f $ These+              (PA.indexPrimArray l n)+              (PA.indexPrimArray r n)+          | isLftShort ->+            PA.writePrimArray sa n+            $ f $ That $ PA.indexPrimArray r n+          | otherwise ->+            PA.writePrimArray sa n+            $ f $ This $ PA.indexPrimArray l n+    PA.unsafeFreezePrimArray sa+  {-# INLINE [1] calignWith #-}++instance CAlign PA.PrimArray where+  cnil = PA.primArrayFromListN 0 []+  {-# INLINE [1] cnil #-}++instance (MT.IsSequence mono, MonoZip mono)+  => CSemialign (WrapMono mono) where+  calignWith f = coerce go+    where+      go :: mono -> mono -> mono+      go ls rs+        | lenL == lenR = ozipWith (fmap f . These) ls rs+        | lenL < lenR  =+            ozipWith (fmap f . These) ls rs+            <> omap (f . That) (MT.drop (fromIntegral lenL) rs)+        | otherwise  =+            ozipWith (fmap f . These) ls rs+            <> omap (f . This) (MT.drop (fromIntegral lenL) ls)+        where lenL = olength ls+              lenR = olength rs++instance (MT.IsSequence mono, MonoZip mono)+  => CAlign (WrapMono mono) where+  cnil = WrapMono mempty++csalign :: (CSemialign f, Dom f a, Semigroup a)+  => f a -> f a -> f a+{-# INLINE [1] csalign #-}+csalign = calignWith $ mergeThese (<>)++cpadZip+  :: (CSemialign f, Dom f a, Dom f b, Dom f (Maybe a, Maybe b))+  => f a -> f b -> f (Maybe a, Maybe b)+{-# INLINE [1] cpadZip #-}+cpadZip = calignWith (fromThese Nothing Nothing . bimap Just Just)++cpadZipWith+  :: (CSemialign f, Dom f a, Dom f b, Dom f c)+  => (Maybe a -> Maybe b -> c)+  -> f a -> f b -> f c+{-# INLINE [1] cpadZipWith #-}+cpadZipWith f = calignWith $+  uncurry f . fromThese Nothing Nothing . bimap Just Just
+ src/Control/Subcategory/Wrapper/Internal.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE CPP, GADTs, InstanceSigs, KindSignatures, PatternSynonyms #-}+{-# LANGUAGE RankNTypes, RoleAnnotations, ScopedTypeVariables          #-}+{-# LANGUAGE StandaloneDeriving, TemplateHaskell, TypeApplications     #-}+{-# LANGUAGE TypeFamilies, TypeOperators, UndecidableSuperClasses      #-}+module Control.Subcategory.Wrapper.Internal where+import Control.Applicative+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 808+import Control.Monad.Fail+#endif+import Control.Monad.Fix    (MonadFix)+import Control.Monad.Zip    (MonadZip)+import Data.Coerce+import Data.Kind            (Type)+import Data.MonoTraversable+import Data.Pointed+import Data.Semialign       (Align, Unalign)+import Data.Zip             (Semialign, Unzip, Zip)+import GHC.Base             (MonadPlus)++newtype WrapFunctor f (a :: Type) = WrapFunctor {runFunctor :: f a}+  deriving newtype (Functor, Applicative, Alternative, Monad, Foldable)+  deriving newtype (MonadPlus, MonadFix, MonadFail)+  deriving newtype (Pointed, MonadZip, Unalign, Align, Semialign, Zip,  Unzip)++instance Traversable f => Traversable (WrapFunctor f) where+  traverse f = fmap WrapFunctor . traverse f . runFunctor+++type role WrapMono representational nominal+-- | Similar to 'WrappedMono' from @mono-traversable,+--   but uses @newtype@ instaed of GADTs, which is efficient.+--   To restrict the construction, we hide genuine constructor+--   and expose the constrained pattern synonym 'WrapMono' and+--   specifies type roles tightly (note: the role for @mono@+--   should NOT be representational honestly; indeed, @WrapMono mono a@+--   could be coerced to @WrapMono mono' a@ iff @mono@ and @mono' are+--   representationally equivalent __AND__ @Element a ~ Element a@.)+newtype WrapMono mono b = WrapMono' mono+  deriving newtype (MonoFoldable, MonoFunctor, Monoid, Semigroup, MonoPointed)+  deriving newtype (GrowingAppend)++type instance Element (WrapMono mono b) = Element mono++pattern WrapMono :: b ~ Element mono => b ~ Element mono => mono -> WrapMono mono b+pattern WrapMono {unwrapMono} = WrapMono' unwrapMono++coerceToMono :: WrapMono mono (Element mono) -> mono+{-# INLINE coerceToMono #-}+coerceToMono = coerce++withMonoCoercible+  :: (Coercible (WrapMono mono (Element mono)) mono => r)+  -> r+{-# INLINE withMonoCoercible #-}+withMonoCoercible = id
+ src/Control/Subcategory/Zip.hs view
@@ -0,0 +1,386 @@+{-# LANGUAGE CPP, DerivingVia, StandaloneDeriving, TypeOperators #-}+module Control.Subcategory.Zip+  ( CZip(..),+    CUnzip(..),+    cunzipDefault,+    CZippy(..),+    CRepeat(..),+    module Control.Subcategory.Semialign+  ) where+import           Control.Applicative                  (ZipList (..))+import           Control.Arrow                        (Arrow ((&&&)), (***))+import           Control.Monad.Zip                    (MonadZip (mzip),+                                                       mzipWith)+import           Control.Subcategory.Functor+import           Control.Subcategory.Semialign+import           Control.Subcategory.Wrapper.Internal+import           Data.Coerce                          (coerce)+import           Data.Containers+import           Data.Functor.Compose                 (Compose (..))+import           Data.Functor.Identity+import qualified Data.Functor.Product                 as SOP+import           Data.Hashable                        (Hashable)+import qualified Data.HashMap.Strict                  as HM+import qualified Data.IntMap.Strict                   as IM+import qualified Data.List.NonEmpty                   as NE+import qualified Data.Map.Strict                      as M+import           Data.MonoTraversable+import qualified Data.Primitive.Array                 as A+import qualified Data.Primitive.PrimArray             as PA+import qualified Data.Primitive.SmallArray            as SA+import           Data.Proxy+import           Data.Semigroup                       (Option (..))+import qualified Data.Sequence                        as Seq+import qualified Data.Sequences                       as MT+import           Data.Tree+import qualified Data.Vector                          as V+import qualified Data.Vector.Generic                  as G+import qualified Data.Vector.Primitive                as Prim+import qualified Data.Vector.Primitive                as PV+import qualified Data.Vector.Storable                 as S+import qualified Data.Vector.Unboxed                  as U+import           Data.Zip+import           GHC.Generics                         ((:*:) (..), (:.:) (..))+import           Prelude                              hiding (repeat, unzip,+                                                       zip, zipWith)+import qualified Prelude                              as P++class CSemialign f => CZip f where+  czipWith+    :: (Dom f a, Dom f b, Dom f c)+    => (a -> b -> c) -> f a -> f b -> f c+  czip+    :: (Dom f a, Dom f b, Dom f (a, b))+    => f a -> f b -> f (a, b)+  {-# INLINE [1] czip #-}+  czip = czipWith (,)++instance Zip f => CZip (WrapFunctor f) where+  czip = zip+  {-# INLINE [1] czip #-}+  czipWith = zipWith+  {-# INLINE [1] czipWith #-}++deriving via WrapFunctor [] instance CZip []+deriving via WrapFunctor Maybe instance CZip Maybe+deriving newtype instance CZip Option+deriving via WrapFunctor ZipList instance CZip ZipList+deriving via WrapFunctor Identity instance CZip Identity+deriving via WrapFunctor NE.NonEmpty instance CZip NE.NonEmpty+deriving via WrapFunctor Tree instance CZip Tree+deriving via WrapFunctor ((->) e) instance CZip ((->) e)++#if MIN_VERSION_semialign(1,1,0)+deriving via WrapFunctor Seq.Seq instance CZip Seq.Seq+deriving via WrapFunctor (M.Map k) instance Ord k => CZip (M.Map k)+deriving via WrapFunctor (HM.HashMap k)+  instance (Eq k, Hashable k)+  => CZip (HM.HashMap k)+deriving via WrapFunctor IM.IntMap instance CZip IM.IntMap+#else+instance CZip Seq.Seq where+  czipWith = Seq.zipWith+  {-# INLINE [1] czipWith #-}+  czip = Seq.zip+  {-# INLINE [1] czip #-}+instance Ord k => CZip (M.Map k) where+  czipWith = M.intersectionWith+  {-# INLINE [1] czipWith #-}+instance (Eq k, Hashable k) => CZip (HM.HashMap k) where+  czipWith = HM.intersectionWith+  {-# INLINE [1] czipWith #-}+instance CZip IM.IntMap where+  czipWith = IM.intersectionWith+  {-# INLINE [1] czipWith #-}+#endif+++instance CZip V.Vector where+  czip = V.zip+  {-# INLINE [1] czip #-}+  czipWith = V.zipWith+  {-# INLINE [1] czipWith #-}++instance CZip U.Vector where+  czip = U.zip+  {-# INLINE [1] czip #-}+  czipWith = U.zipWith+  {-# INLINE [1] czipWith #-}++instance CZip S.Vector where+  czipWith = S.zipWith+  {-# INLINE [1] czipWith #-}++instance CZip Prim.Vector where+  czipWith = Prim.zipWith+  {-# INLINE [1] czipWith #-}++instance CZip Proxy where+  czip = const $ const Proxy+  {-# INLINE czip #-}+  czipWith = const $ const $ const Proxy+  {-# INLINE czipWith #-}++instance (CZip f, CZip g) => CZip (SOP.Product f g) where+  czipWith f (SOP.Pair a b) (SOP.Pair c d) =+    SOP.Pair (czipWith f a c) (czipWith f b d)+  {-# INLINE [1] czipWith #-}+  czip (SOP.Pair a b) (SOP.Pair c d) =+    SOP.Pair (czip a c) (czip b d)+  {-# INLINE [1] czip #-}++instance (CZip f, CZip g) => CZip (f :*: g) where+  czipWith f (a :*: b) (c :*: d) =+    czipWith f a c :*: czipWith f b d+  {-# INLINE [1] czipWith #-}+  czip (a :*: b) (c :*: d) =+    czip a c :*: czip b d+  {-# INLINE [1] czip #-}++instance (CZip f, CZip g) => CZip (Compose f g) where+  czipWith f (Compose a) (Compose b) =+    Compose $ czipWith (czipWith f) a b+  {-# INLINE [1] czipWith #-}+  czip (Compose a) (Compose b) =+    Compose $ czipWith czip a b+  {-# INLINE [1] czip #-}++instance (CZip f, CZip g) => CZip (f :.: g) where+  czipWith f (Comp1 a) (Comp1 b) =+    Comp1 $ czipWith (czipWith f) a b+  {-# INLINE [1] czipWith #-}+  czip (Comp1 a) (Comp1 b) =+    Comp1 $ czipWith czip a b+  {-# INLINE [1] czip #-}++{-# RULES+"czip/List"+  czip = P.zip+"czipWith/List"+  czipWith = P.zipWith+"czip/NonEmpty"+  czip = NE.zip+"czipWith/NonEmpty"+  czipWith = NE.zipWith+"czip/Seq"+  czip = Seq.zip+"czipWith/Seq"+  czipWith = Seq.zipWith+  #-}++class CZip f => CRepeat f where+  crepeat :: Dom f a => a -> f a++newtype CZippy f a = CZippy { runCZippy :: f a }+  deriving (Show, Read)+  deriving newtype (Functor, Zip, Semialign, Eq, Ord)+  deriving newtype (Constrained)+#if MIN_VERSION_semialign(1,1,0)+  deriving newtype (Repeat)+#endif++instance CFunctor f => CFunctor (CZippy f) where+  cmap = coerce $ cmap @f @a @b+    :: forall a b. (Dom f a, Dom f b) => (a -> b) -> CZippy f a -> CZippy f b+  {-# INLINE [1] cmap #-}++instance CSemialign f => CSemialign (CZippy f) where+  calignWith = \f -> coerce $ calignWith @f f+  {-# INLINE [1] calignWith #-}++instance CZip f => CZip (CZippy f) where+  czipWith f = coerce $ czipWith @f f+  {-# INLINE [1] czipWith #-}++instance CRepeat f => CRepeat (CZippy f) where+  crepeat = CZippy . crepeat+  {-# INLINE [1] crepeat #-}++instance (CZip f, Dom f a, Semigroup a) => Semigroup (CZippy f a) where+  (<>) = coerce $ czipWith @f ((<>) @a)+  {-# INLINE [1] (<>) #-}++instance (CRepeat f, Dom f a, Monoid a) => Monoid (CZippy f a) where+  mempty = coerce $ crepeat @f (mempty @a)+  {-# INLINE [1] mempty #-}++#if MIN_VERSION_semialign(1,1,0)+instance Repeat f => CRepeat (WrapFunctor f) where+  crepeat = coerce $ repeat @f @a+    :: forall a. a -> WrapFunctor f a+  {-# INLINE [1] crepeat #-}+deriving via WrapFunctor [] instance CRepeat []+deriving via WrapFunctor Maybe instance CRepeat Maybe+deriving newtype instance CRepeat Option+deriving via WrapFunctor ZipList instance CRepeat ZipList+deriving via WrapFunctor Identity instance CRepeat Identity+deriving via WrapFunctor NE.NonEmpty instance CRepeat NE.NonEmpty+deriving via WrapFunctor Tree instance CRepeat Tree+deriving via WrapFunctor ((->) e) instance CRepeat ((->) e)+#else+instance CRepeat [] where+  crepeat = P.repeat+  {-# INLINE [1] crepeat #-}+instance CRepeat Maybe where+  crepeat = Just+  {-# INLINE [1] crepeat #-}+deriving newtype instance CRepeat Option+deriving newtype instance CRepeat ZipList+instance CRepeat Identity where+  crepeat = Identity+  {-# INLINE [1] crepeat #-}+instance CRepeat NE.NonEmpty where+  crepeat = NE.repeat+  {-# INLINE [1] crepeat #-}+instance CRepeat Tree where+  crepeat x = n where n = Node x (P.repeat n)+  {-# INLINE [1] crepeat #-}+instance CRepeat Proxy where+  crepeat = const Proxy+  {-# INLINE [1] crepeat #-}+instance CRepeat ((->) e) where+  crepeat = const+  {-# INLINE [1] crepeat #-}+#endif++instance CZip SA.SmallArray where+  czip = mzip+  {-# INLINE [1] czip #-}+  czipWith = mzipWith+  {-# INLINE [1] czipWith #-}++instance CZip A.Array where+  czip = mzip+  {-# INLINE [1] czip #-}+  czipWith = mzipWith+  {-# INLINE [1] czipWith #-}++instance CZip PA.PrimArray where+  czipWith f l r =+    PA.generatePrimArray+      (PA.sizeofPrimArray l `min` PA.sizeofPrimArray r) $ \n ->+        f (PA.indexPrimArray l n) (PA.indexPrimArray r n)+  {-# INLINE [1] czipWith #-}++class CZip f => CUnzip f where+  cunzip+    :: (Dom f (a, b), Dom f a, Dom f b)+    => f (a, b) -> (f a, f b)+  {-# INLINE [1] cunzip #-}+  cunzip = cunzipWith id++  cunzipWith+    :: (Dom f c, Dom f a, Dom f b)+    => (c -> (a, b)) -> f c -> (f a, f b)++cunzipDefault+  :: (CFunctor f, Dom f (a, b), Dom f a, Dom f b)+  => f (a, b) -> (f a, f b)+{-# INLINE cunzipDefault #-}+cunzipDefault = cmap fst &&& cmap snd++#if MIN_VERSION_semialign(1,1,0)+instance Unzip f => CUnzip (WrapFunctor f) where+#else+instance (Zip f, Unzip f) => CUnzip (WrapFunctor f) where+#endif+  cunzip :: forall a b. WrapFunctor f (a, b) -> (WrapFunctor f a, WrapFunctor f b)+  {-# INLINE cunzip #-}+  cunzip = coerce $ unzip @f @a @b+  {-# INLINE cunzipWith #-}+  cunzipWith = coerce $ unzipWith @f @c @a @b+    :: forall a b c. (c -> (a, b)) -> WrapFunctor f c -> (WrapFunctor f a, WrapFunctor f b)++instance CUnzip [] where+  cunzip = P.unzip+  {-# INLINE [1] cunzip #-}+  cunzipWith = \f -> P.unzip . map f+  {-# INLINE [1] cunzipWith #-}++deriving via WrapFunctor Maybe instance CUnzip Maybe+#if MIN_VERSION_semialign(1,1,0)+deriving via WrapFunctor Option instance CUnzip Option+#endif+deriving via [] instance CUnzip ZipList+deriving via WrapFunctor Identity instance CUnzip Identity+deriving via WrapFunctor NE.NonEmpty instance CUnzip NE.NonEmpty+deriving via WrapFunctor Tree instance CUnzip Tree+instance CUnzip V.Vector where+  cunzip = V.unzip+  {-# INLINE [1] cunzip #-}+  cunzipWith = \f -> V.unzip . V.map f+  {-# INLINE [1] cunzipWith #-}+instance CUnzip U.Vector where+  cunzip = U.unzip+  {-# INLINE [1] cunzip #-}+  cunzipWith = \f -> U.unzip . U.map f+  {-# INLINE [1] cunzipWith #-}++instance CUnzip PV.Vector where+  cunzip = G.unzip+  {-# INLINE [1] cunzip #-}+  cunzipWith = \f ->+    (G.convert *** G.convert)  . cunzipWith @V.Vector f . V.convert+  {-# INLINE [1] cunzipWith #-}++instance CUnzip S.Vector where+  cunzip = G.unzip+  {-# INLINE [1] cunzip #-}+  cunzipWith = \f ->+    (G.convert *** G.convert)  . cunzipWith @V.Vector f . V.convert+  {-# INLINE [1] cunzipWith #-}+deriving via WrapFunctor Proxy instance CUnzip Proxy+#if MIN_VERSION_semialign(1,1,0)+deriving via WrapFunctor Seq.Seq instance CUnzip Seq.Seq+deriving via WrapFunctor (M.Map k) instance Ord k => CUnzip (M.Map k)+deriving via WrapFunctor IM.IntMap instance CUnzip IM.IntMap+deriving via WrapFunctor (HM.HashMap k)+  instance (Eq k, Hashable k) => CUnzip (HM.HashMap k)+#endif++instance (CUnzip f, CUnzip g) => CUnzip (SOP.Product f g) where+  cunzipWith f (SOP.Pair a b)  =+    (SOP.Pair al bl, SOP.Pair ar br)+    where+      ~(al, ar) = cunzipWith f a+      ~(bl, br) = cunzipWith f b+  {-# INLINE [1] cunzipWith #-}+  cunzip (SOP.Pair a b)  =+    (SOP.Pair al bl, SOP.Pair ar br)+    where+      ~(al, ar) = cunzip a+      ~(bl, br) = cunzip b+  {-# INLINE [1] cunzip #-}++instance (CUnzip f, CUnzip g) => CUnzip (f :*: g) where+  cunzipWith f (a :*: b)  =+    (al :*: bl, ar :*: br)+    where+      ~(al, ar) = cunzipWith f a+      ~(bl, br) = cunzipWith f b+  {-# INLINE [1] cunzipWith #-}+  cunzip (a :*: b)  =+    (al :*: bl, ar :*: br)+    where+      ~(al, ar) = cunzip a+      ~(bl, br) = cunzip b+  {-# INLINE [1] cunzip #-}++instance (CUnzip f, CUnzip g) => CUnzip (Compose f g) where+  cunzipWith f (Compose a) = (Compose y, Compose z) where+    ~(y, z) = cunzipWith (cunzipWith f) a+  {-# INLINE [1] cunzipWith #-}++instance (CUnzip f, CUnzip g) => CUnzip (f :.: g) where+  cunzipWith f (Comp1 a) = (Comp1 y, Comp1 z) where+    ~(y, z) = cunzipWith (cunzipWith f) a+  {-# INLINE [1] cunzipWith #-}++instance (MT.IsSequence mono, MonoZip mono)+  => CZip (WrapMono mono) where+    czipWith f = coerce $ ozipWith @mono f+    {-# INLINE [1] czipWith #-}++instance (MT.IsSequence mono, MonoZip mono)+  => CUnzip (WrapMono mono) where+    cunzipWith f = coerce $ omap @mono (fst . f) &&& omap @mono (snd . f)
+ subcategories.cabal view
@@ -0,0 +1,112 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.33.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 06bb5130d08da403db0bdee15f708a050dca4d9ba1adb757dd932c9586b3b0c2++name:           subcategories+version:        0.1.0.0+synopsis:       Subcategories induced by class constraints+description:    Please see the README on GitHub at <https://github.com/konn/subcategories#readme>+category:       Data+homepage:       https://github.com/konn/subcategories#readme+bug-reports:    https://github.com/konn/subcategories/issues+author:         Hiromi ISHII+maintainer:     konn.jinro _at_ gmail.com+copyright:      2018 (c) Hiromi ISHII+license:        BSD3+license-file:   LICENSE+tested-with:    GHC == 8.6.5, GHC == 8.8.3, GHC == 8.10.1+build-type:     Simple+extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/konn/subcategories++library+  exposed-modules:+      Control.Subcategory+      Control.Subcategory.Alternative+      Control.Subcategory.Alternative.Class+      Control.Subcategory.Applicative+      Control.Subcategory.Applicative.Class+      Control.Subcategory.Bind+      Control.Subcategory.Foldable+      Control.Subcategory.Functor+      Control.Subcategory.Pointed+      Control.Subcategory.RebindableSyntax+      Control.Subcategory.Semialign+      Control.Subcategory.Zip+  other-modules:+      Control.Subcategory.Wrapper.Internal+  hs-source-dirs:+      src+  default-extensions: ConstraintKinds DataKinds DefaultSignatures DerivingStrategies FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures MultiParamTypeClasses PolyKinds ScopedTypeVariables TypeApplications TypeFamilies TypeInType UndecidableInstances+  ghc-options: -Wall+  build-depends:+      base >=4.7 && <5+    , containers+    , data-default+    , foldl+    , hashable+    , mono-traversable+    , pointed+    , primitive+    , reflection+    , semialign+    , template-haskell+    , text+    , these+    , unordered-containers+    , vector+    , vector-algorithms+    , vector-builder+  default-language: Haskell2010++test-suite subcategories-test+  type: exitcode-stdio-1.0+  main-is: spec.hs+  other-modules:+      Control.Subcategory.FoldableSpec+      Control.Subcategory.FunctorSpec+      Control.Subcategory.ZipSpec+      Shared+      Paths_subcategories+  hs-source-dirs:+      test+  default-extensions: ConstraintKinds DataKinds DefaultSignatures DerivingStrategies FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures MultiParamTypeClasses PolyKinds ScopedTypeVariables TypeApplications TypeFamilies TypeInType UndecidableInstances+  ghc-options: -Wall -fno-hpc+  build-tool-depends:+      tasty-discover:tasty-discover+  build-depends:+      QuickCheck+    , base >=4.7 && <5+    , bytestring+    , containers+    , data-default+    , foldl+    , hashable+    , inspection-testing+    , mono-traversable+    , pointed+    , primitive+    , reflection+    , semialign+    , subcategories+    , tasty+    , tasty-expected-failure+    , tasty-hunit+    , tasty-quickcheck+    , template-haskell+    , text+    , these+    , unordered-containers+    , vector+    , vector-algorithms+    , vector-builder+  default-language: Haskell2010
+ test/Control/Subcategory/FoldableSpec.hs view
@@ -0,0 +1,208 @@+{-# LANGUAGE AllowAmbiguousTypes, TemplateHaskell #-}+{-# OPTIONS_GHC -dsuppress-idinfo -dsuppress-coercions+      -dsuppress-type-applications+      -dsuppress-module-prefixes -dsuppress-type-signatures+      -dsuppress-uniques #-}+module Control.Subcategory.FoldableSpec where+import Control.Subcategory.Foldable+import Control.Subcategory.Functor++import           Data.MonoTraversable+import qualified Data.Vector           as V+import qualified Data.Vector.Generic   as G+import qualified Data.Vector.Primitive as P+import qualified Data.Vector.Storable  as S+import qualified Data.Vector.Unboxed   as U+import           Shared+import           Test.Inspection+import           Test.Tasty++cfoldr_uvec :: (Int -> b -> b) -> b -> U.Vector Int -> b+cfoldr_uvec = cfoldr++cfoldr_uvec_poly :: U.Unbox a => (a -> b -> b) -> b -> U.Vector a -> b+cfoldr_uvec_poly = cfoldr++foldr_uvec :: (Int -> b -> b) -> b -> U.Vector Int -> b+foldr_uvec = U.foldr++cfoldr_svec :: (Int -> b -> b) -> b -> S.Vector Int -> b+cfoldr_svec = cfoldr++cfoldr_svec_poly :: S.Storable a => (a -> b -> b) -> b -> S.Vector a -> b+cfoldr_svec_poly = cfoldr++foldr_svec :: (Int -> b -> b) -> b -> S.Vector Int -> b+foldr_svec = S.foldr++cfoldr_pvec :: (Int -> b -> b) -> b -> P.Vector Int -> b+cfoldr_pvec = cfoldr++cfoldr_pvec_poly :: P.Prim a => (a -> b -> b) -> b -> P.Vector a -> b+cfoldr_pvec_poly = cfoldr++foldr_pvec :: (Int -> b -> b) -> b -> P.Vector Int -> b+foldr_pvec = P.foldr++cfoldr_bvec :: (a -> b -> b) -> b -> V.Vector a -> b+cfoldr_bvec = cfoldr++foldr_bvec :: (a -> b -> b) -> b -> V.Vector a -> b+foldr_bvec = V.foldr++cfoldr_list :: (a -> b -> b) -> b -> [a] -> b+cfoldr_list = cfoldr++foldr_list :: (a -> b -> b) -> b -> [a] -> b+foldr_list = foldr++test_cfoldr :: TestTree+test_cfoldr = testGroup "cfoldr"+  [ testGroup "List"+    [ $(inspecting "has the same representation as V.foldr"+        $ 'cfoldr_list ==- 'foldr_list+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cfoldr_list+      )+    ]+  , testGroup "BVector"+    [ $(inspecting "has the same representation as V.foldr"+        $ 'cfoldr_bvec ==- 'foldr_bvec+      )+    , $(inspecting "has no instance dictionary except G.Vector"+      $ 'cfoldr_bvec `hasNoTypeClassesExcept` [''G.Vector]+      )+    ]+  , testGroup "UVector"+    [ $(inspecting "has the same representation as U.foldr (if an element is concrete)"+        $ 'cfoldr_uvec ==- 'foldr_uvec+      )+    , $(inspecting "has no instance dictionary other than Unbox (if polymorphic)"+      $ 'cfoldr_uvec_poly `hasNoTypeClassesExcept` [''U.Unbox]+      )+    ]+  , testGroup "SVector"+    [ $(inspecting "has the same representation as S.foldr (if an element is concrete)"+        $ 'cfoldr_svec ==- 'foldr_svec+      )+    , $(inspecting "has no instance dictionary other than Storable (if polymorphic)"+      $ 'cfoldr_svec_poly `hasNoTypeClassesExcept` [''S.Storable]+      )+    ]+  , testGroup "PVector"+    [ $(inspecting "has the same representation as P.foldr (if an element is concrete)"+        $ 'cfoldr_pvec ==- 'foldr_pvec+      )+    , $(inspecting "has no instance dictionary other than Storable (if polymorphic)"+      $ 'cfoldr_pvec_poly `hasNoTypeClassesExcept` [''P.Prim]+      )+    ]+  ]++cfoldMap_uvec :: Monoid w => (Int -> w) -> U.Vector Int -> w+cfoldMap_uvec = cfoldMap++ofoldMap_uvec :: Monoid w => (Int -> w) -> U.Vector Int -> w+ofoldMap_uvec = ofoldMap++test_cfoldMap :: TestTree+test_cfoldMap = testGroup "cfoldMap"+    [ testGroup "UVector"+      [ $(inspecting "has the same rep as ofoldMap (if elements concrete)"+        $ 'cfoldMap_uvec ==- 'ofoldMap_uvec+        )+      ]+    ]++cinit_list :: [a] -> [a]+cinit_list = cinit++init_list :: [a] -> [a]+{-# INLINE init_list #-}+init_list = init++test_cinit :: TestTree+test_cinit = testGroup "cinit"+  [ testGroup "List"+    [ $(inspecting "has the same represeitation as Prelude.init"+      $ 'cinit_list ==- 'init_list+      )+    ]+  ]++ctoList_list :: [a] -> [a]+ctoList_list = ctoList++list_id :: [a] -> [a]+list_id = id++list_id_lam :: [a] -> [a]+list_id_lam = \x -> x++cfromList_list :: [a] -> [a]+cfromList_list = cfromList++test_ctoList :: TestTree+test_ctoList = testGroup "ctoList"+  [ testGroup "List"+    [ $(inspecting "has the same represeitation as Prelude.id"+      $ 'ctoList_list ==- 'list_id+      )+    ]+  ]++test_cfromList :: TestTree+test_cfromList = testGroup "cfromList"+  [ testGroup "List"+    [ $(inspecting "has the same represeitation as Prelude.id"+      $ 'cfromList_list ==- 'list_id+      )+    ]+  ]+++ctoFromList_list :: [a] -> [a]+ctoFromList_list = ctoList . cfromList @[]++ctoFromList_bvec :: [a] -> [a]+ctoFromList_bvec xs = ctoList (cfromList @V.Vector xs)++ctoFromList_poly :: forall f a. (CFreeMonoid f, Dom f a) => [a] -> [a]+ctoFromList_poly xs = ctoList (cfromList @f xs)++list_id_with_constr :: forall f a. (CFreeMonoid f, Dom f a) => [a] -> [a]+list_id_with_constr = \xs -> xs++test_rules :: TestTree+test_rules = testGroup "Rewrite rules"+  [ testGroup "ctoList . cfromList = ctoList"+    [ $(inspecting "List"+        $ 'ctoFromList_list ==- 'list_id_lam+      )+    , $(inspecting "Boxed vector"+        $ 'ctoFromList_bvec ==- 'list_id_lam+      )+    , $(inspecting "Polymorphic (up to dictionary leftover)"+        $ 'ctoFromList_poly ==- 'list_id_with_constr+      )+    ]+  ]++cgen_bvec, gen_bvec :: Int -> (Int -> a) -> V.Vector a+cgen_bvec = cgenerate+gen_bvec = V.generate++test_generate :: TestTree+test_generate = testGroup "cgenerate"+  [ $(inspecting "Boxed Vector" $ 'cgen_bvec ==- 'gen_bvec)+  ]++crev_list, rev_list :: [a] -> [a]+crev_list = creverse+rev_list = reverse++test_reverse :: TestTree+test_reverse = testGroup "creverse"+  [ $(inspecting "List" $ 'crev_list ==- 'rev_list)+  ]
+ test/Control/Subcategory/FunctorSpec.hs view
@@ -0,0 +1,231 @@+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -dsuppress-idinfo -dsuppress-coercions+      -dsuppress-type-applications+      -dsuppress-module-prefixes -dsuppress-type-signatures+      -dsuppress-uniques #-}+module Control.Subcategory.FunctorSpec where+import Control.Subcategory.Functor++import qualified Data.ByteString           as BS+import           Data.Hashable             (Hashable)+import           Data.HashSet              (HashSet)+import qualified Data.HashSet              as HS+import           Data.IntSet               (IntSet)+import qualified Data.IntSet               as IS+import qualified Data.Primitive.Array      as A+import qualified Data.Primitive.PrimArray  as PA+import qualified Data.Primitive.SmallArray as SA+import qualified Data.Sequence             as Seq+import           Data.Set                  (Set)+import qualified Data.Set                  as Set+import qualified Data.Text                 as T+import qualified Data.Vector               as V+import qualified Data.Vector.Primitive     as P+import qualified Data.Vector.Storable      as S+import qualified Data.Vector.Unboxed       as U+import           Data.Word                 (Word8)+import           Shared+import           Test.Inspection+import           Test.Tasty++cmap_list :: (a -> b) -> [a] -> [b]+cmap_list = cmap++map_list :: (a -> b) -> [a] -> [b]+map_list = map++cmap_seq :: (a -> b) -> Seq.Seq a -> Seq.Seq b+cmap_seq = cmap++map_seq :: (a -> b) -> Seq.Seq a -> Seq.Seq b+map_seq = fmap++cmap_intset :: (Int -> Int) -> WrapMono IntSet Int -> WrapMono IntSet Int+cmap_intset = cmap++map_intset :: (Int -> Int) -> IntSet -> IntSet+map_intset = IS.map++cmap_uvec :: (Int -> Bool) -> U.Vector Int -> U.Vector Bool+cmap_uvec = cmap++map_uvec :: (Int -> Bool) -> U.Vector Int -> U.Vector Bool+map_uvec = U.map++cmap_bvec :: (a -> b) -> V.Vector a -> V.Vector b+cmap_bvec = cmap++map_bvec :: (a -> b) -> V.Vector a -> V.Vector b+map_bvec = V.map++cmap_svec :: (Int -> Bool) -> S.Vector Int -> S.Vector Bool+cmap_svec = cmap++map_svec :: (Int -> Bool) -> S.Vector Int -> S.Vector Bool+map_svec = S.map++cmap_pvec :: (Int -> Word) -> P.Vector Int -> P.Vector Word+cmap_pvec = cmap++map_pvec :: (Int -> Word) -> P.Vector Int -> P.Vector Word+map_pvec = P.map++cmap_smallarray :: (Int -> Word) -> SA.SmallArray Int -> SA.SmallArray Word+cmap_smallarray = cmap++map_smallarray :: (Int -> Word) -> SA.SmallArray Int -> SA.SmallArray Word+map_smallarray = fmap++cmap_array :: (Int -> Word) -> A.Array Int -> A.Array Word+cmap_array = cmap++map_array :: (Int -> Word) -> A.Array Int -> A.Array Word+map_array = fmap++cmap_primarray :: (Int -> Word) -> PA.PrimArray Int -> PA.PrimArray Word+cmap_primarray = cmap++map_primarray :: (Int -> Word) -> PA.PrimArray Int -> PA.PrimArray Word+map_primarray = PA.mapPrimArray++cmap_Maybe :: (a -> b) -> Maybe a -> Maybe b+cmap_Maybe = cmap++map_Maybe :: (a -> b) -> Maybe a -> Maybe b+map_Maybe = fmap++cmap_Set :: (Ord b) => (Int -> b) -> Set Int -> Set b+cmap_Set = cmap++map_Set :: Ord b => (Int -> b) -> Set Int -> Set b+map_Set = Set.map++cmap_HashSet+  :: (Hashable b, Eq b)+  => (String -> Maybe b) -> HashSet String -> HashSet (Maybe b)+cmap_HashSet = cmap++map_HashSet+  :: (Hashable b, Eq b) => (String -> Maybe b) -> HashSet String -> HashSet (Maybe b)+{-# INLINE map_HashSet #-}+map_HashSet = HS.map++cmap_MonoBS :: (Word8 -> Word8) -> WrapMono BS.ByteString Word8 -> WrapMono BS.ByteString Word8+cmap_MonoBS = cmap++map_BS :: (Word8 -> Word8) -> BS.ByteString -> BS.ByteString+{-# INLINE map_BS #-}+map_BS = BS.map++cmap_MonoText :: (Char -> Char) -> WrapMono T.Text Char -> WrapMono T.Text Char+cmap_MonoText = cmap++map_Text :: (Char -> Char) -> T.Text -> T.Text+{-# INLINE map_Text #-}+map_Text = T.map++test_cmap :: TestTree+test_cmap = testGroup "cmap"+  [ testGroup "list"+    [ $(inspecting "has the same representation as Prelude.map"+        $ 'cmap_list ==- 'map_list+      )+    ]+  , testGroup "Seq"+    [ $(inspecting "has the same representation as fmap"+        $ 'cmap_seq ==- 'map_seq+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_seq+      )+    ]+  , testGroup "IntSet"+    [ $(inspecting "has the same representation as IntSet.map"+        $ 'cmap_intset ==- 'map_intset+      )+    ]+  , testGroup "BVector"+    [ $(inspecting "has the same representation as V.map"+        $ 'cmap_bvec ==- 'map_bvec+      )+    ]+  , testGroup "UVector"+    [ $(inspecting "has the same representation as U.map"+        $ 'cmap_uvec ==- 'map_uvec+      )+    ]+  , testGroup "SVector"+    [ $(inspecting "has the same representation as S.map"+        $ 'cmap_svec ==- 'map_svec+      )+    ]+  , testGroup "PVector"+    [ $(inspecting "has the same representation as P.map"+        $ 'cmap_pvec ==- 'map_pvec+      )+    ]+  , testGroup "SmallArray"+    [ $(inspecting "has the same representation as fmap"+        $ 'cmap_smallarray ==- 'map_smallarray+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_smallarray+      )+    ]+  , testGroup "Array"+    [ $(inspecting "has the same representation as fmap"+        $ 'cmap_array ==- 'map_array+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_array+      )+    ]+  , testGroup "PrimArray"+    [ $(inspecting "has the same representation as PA.mapPrimArray"+        $ 'cmap_primarray ==- 'map_primarray+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_primarray+      )+    ]+  , testGroup "Maybe"+    [ $(inspecting "has the same representation as fmap"+      $ 'cmap_Maybe ==- 'map_Maybe+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_Maybe+      )+    ]+  , testGroup "Set"+    [ $(inspecting "has the same representation as Set.map"+      $ 'cmap_Set ==- 'map_Set+      )+    , $(inspecting "has no instance dictionary except Ord"+      $ 'cmap_Set `hasNoTypeClassesExcept` [''Ord]+      )+    ]+  , testGroup "HashSet"+    [ $(inspecting "has the same representation as HS.map, if the first argument is concrete"+      $ 'cmap_HashSet ==- 'map_HashSet+      )+    , $(inspecting "has no instance dictionary except EQ and Hashable"+      $ 'cmap_HashSet `hasNoTypeClassesExcept` [''Eq, ''Hashable]+      )+    ]+  , testGroup "WrapMono ByteString"+    [ $(inspecting "has the same representation as Data.ByteString.map"+      $ 'cmap_MonoBS ==- 'map_BS+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_MonoBS+      )+    ]+  , testGroup "WrapMono Text"+    [ $(inspecting "has the same representation as Data.Text.map"+      $ 'cmap_MonoText ==- 'map_Text+      )+    , $(inspecting "has no instance dictionary"+      $ hasNoTypeClasses 'cmap_MonoText+      )+    ]+  ]
+ test/Control/Subcategory/ZipSpec.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -dsuppress-idinfo -dsuppress-coercions+      -dsuppress-type-applications+      -dsuppress-module-prefixes -dsuppress-type-signatures+      -dsuppress-uniques #-}+module Control.Subcategory.ZipSpec where+import Control.Subcategory.Zip++import qualified Data.Vector     as V+import           Shared+import           Test.Inspection+import           Test.Tasty++czipWith_vec :: (a -> b -> c) -> V.Vector a -> V.Vector b -> V.Vector c+czipWith_vec = czipWith++zipWith_vec :: (a -> b -> c) -> V.Vector a -> V.Vector b -> V.Vector c+zipWith_vec = V.zipWith++czipWith_list :: (a -> b -> c) -> [a] -> [b] -> [c]+czipWith_list = czipWith++zipWith_list :: (a -> b -> c) -> [a] -> [b] -> [c]+zipWith_list = Prelude.zipWith++test_czipWith :: TestTree+test_czipWith = testGroup "czipWith"+  [ testGroup "list"+    [ $(inspecting "has the same representation as Prelude.zipWith"+        $ 'czipWith_list ==- 'zipWith_list+      )+    ]+  , testGroup "vector"+    [ $(inspecting "has the same representation as Prelude.zipWith"+        $ 'czipWith_vec ==- 'zipWith_vec+      )+    ]+  ]
+ test/Shared.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}+module Shared where+import Control.Exception+import Data.Maybe          (listToMaybe)+import GHC.Stack           (callStack)+import GHC.Stack.Types     (getCallStack)+import Language.Haskell.TH+import Test.Inspection+import Test.Tasty.HUnit++checkInspection+  :: HasCallStack => Result -> Assertion+checkInspection Success{} = pure ()+checkInspection (Failure msg) =+  throwIO $ HUnitFailure (fmap snd $ listToMaybe $ getCallStack callStack) msg++inspecting :: String -> Obligation -> Q Exp+inspecting desc reg =+  [|testCase desc $ checkInspection $(inspectTest reg)|]
+ test/spec.hs view
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --tree-display #-}+module Main where