module Data.Semigroup.Involutive
( Involutive(..)
) where
import GHC.Generics
import Data.Ord
import Data.Semigroup
import Data.Functor.Const
import Data.Functor.Contravariant
import Data.Functor.Identity
import qualified Data.List as List
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as List.NonEmpty
import Data.Proxy
import qualified Data.ByteString as Strict
import qualified Data.ByteString as Strict.ByteString
import qualified Data.ByteString.Lazy as Lazy
import qualified Data.ByteString.Lazy as Lazy.ByteString
import Data.Void
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import qualified Data.Text as Strict
import qualified Data.Text as Strict.Text
import qualified Data.Text.Lazy as Lazy
import qualified Data.Text.Lazy as Lazy.Text
import Data.Vector (Vector)
import qualified Data.Vector as Vector
import Data.Vector.Unboxed (Unbox)
import qualified Data.Vector.Unboxed as Unboxed
import qualified Data.Vector.Unboxed as Unboxed.Vector
import Data.Vector.Storable (Storable)
import qualified Data.Vector.Storable as Storable
import qualified Data.Vector.Storable as Storable.Vector
import Data.Vector.Primitive (Prim)
import qualified Data.Vector.Primitive as Primitive
import qualified Data.Vector.Primitive as Primitive.Vector
class (Semigroup a) => Involutive a where
rev :: a -> a
instance Involutive () where
rev = const ()
{-# INLINE rev #-}
instance Involutive Void where
rev = id
{-# INLINE rev #-}
instance (Involutive a, Involutive b) => Involutive (a, b) where
rev (a, b) = (rev a, rev b)
{-# INLINE rev #-}
instance (Involutive a, Involutive b, Involutive c) => Involutive (a, b, c) where
rev (a, b, c) = (rev a, rev b, rev c)
{-# INLINE rev #-}
instance (Involutive a, Involutive b, Involutive c, Involutive d) => Involutive (a, b, c, d) where
rev (a, b, c, d) = (rev a, rev b, rev c, rev d)
{-# INLINE rev #-}
instance (Involutive a, Involutive b, Involutive c, Involutive d, Involutive e) => Involutive (a, b, c, d, e) where
rev (a, b, c, d, e) = (rev a, rev b, rev c, rev d, rev e)
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Dual a) where
rev = fmap rev
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Identity a) where
rev = fmap rev
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Const a b) where
rev = Const . rev . getConst
{-# INLINE rev #-}
instance (Involutive b) => Involutive (a -> b) where
rev = fmap rev
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Op a b) where
rev = Op . rev . getOp
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Maybe a) where
rev = fmap rev
{-# INLINE rev #-}
instance Involutive [a] where
rev = List.reverse
{-# INLINE rev #-}
instance Involutive (NonEmpty a) where
rev = List.NonEmpty.reverse
{-# INLINE rev #-}
instance (Num a) => Involutive (Sum a) where
rev = negate
{-# INLINE rev #-}
instance (Involutive a) => Involutive (Down a) where
rev (Down a) = Down (rev a)
{-# INLINE rev #-}
instance Involutive (Proxy s) where
rev = const Proxy
{-# INLINE rev #-}
instance Involutive (V1 p) where
rev = id
{-# INLINE rev #-}
instance Involutive (U1 p) where
rev = const U1
{-# INLINE rev #-}
instance (Involutive p) => Involutive (Par1 p) where
rev = Par1 . rev . unPar1
{-# INLINE rev #-}
instance (Involutive (f p)) => Involutive (Rec1 f p) where
rev = Rec1 . rev . unRec1
{-# INLINE rev #-}
instance (Involutive c) => Involutive (K1 i c p) where
rev = K1 . rev . unK1
{-# INLINE rev #-}
instance (Involutive (f p)) => Involutive (M1 i c f p) where
rev = M1 . rev . unM1
{-# INLINE rev #-}
instance (Involutive (f p), Involutive (g p)) => Involutive ((f :*: g) p) where
rev (x :*: y) = rev x :*: rev y
{-# INLINE rev #-}
instance (Involutive (f (g p))) => Involutive ((f :.: g) p) where
rev = Comp1 . rev . unComp1
{-# INLINE rev #-}
instance Involutive Strict.ByteString where
rev = Strict.ByteString.reverse
{-# INLINE rev #-}
instance Involutive Lazy.ByteString where
rev = Lazy.ByteString.reverse
{-# INLINE rev #-}
instance Involutive (Seq a) where
rev = Seq.reverse
{-# INLINE rev #-}
instance Involutive Strict.Text where
rev = Strict.Text.reverse
{-# INLINE rev #-}
instance Involutive Lazy.Text where
rev = Lazy.Text.reverse
{-# INLINE rev #-}
instance Involutive (Vector a) where
rev = Vector.reverse
{-# INLINE rev #-}
instance (Unbox a) => Involutive (Unboxed.Vector a) where
rev = Unboxed.Vector.reverse
{-# INLINE rev #-}
instance (Storable a) => Involutive (Storable.Vector a) where
rev = Storable.Vector.reverse
{-# INLINE rev #-}
instance (Prim a) => Involutive (Primitive.Vector a) where
rev = Primitive.Vector.reverse
{-# INLINE rev #-}