{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
#if __GLASGOW_HASKELL__ >= 708
{-# LANGUAGE EmptyCase #-}
#endif
module Data.Functor.Extend
(
Extend(..)
) where
import Prelude hiding (id, (.))
import Control.Category
import Control.Monad.Trans.Identity
import Data.Functor.Identity
import Data.Functor.Sum as Functor (Sum(..))
import Data.List (tails)
import Data.List.NonEmpty (NonEmpty(..), toList)
#ifdef MIN_VERSION_containers
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.Tree
#endif
#ifdef MIN_VERSION_comonad
import Control.Comonad.Trans.Env
import Control.Comonad.Trans.Store
import Control.Comonad.Trans.Traced
#endif
#ifdef MIN_VERSION_tagged
import Data.Tagged
#endif
#if defined(MIN_VERSION_tagged) || MIN_VERSION_base(4,7,0)
import Data.Proxy
#endif
#ifdef MIN_VERSION_generic_deriving
import Generics.Deriving.Base as Generics
#else
import GHC.Generics as Generics
#endif
import Data.Orphans ()
import qualified Data.Monoid as Monoid
import Data.Semigroup as Semigroup
class Functor w => Extend w where
duplicated :: w a -> w (w a)
extended :: (w a -> b) -> w a -> w b
extended f = fmap f . duplicated
duplicated = extended id
#if __GLASGOW_HASKELL__ >= 708
{-# MINIMAL duplicated | extended #-}
#endif
instance Extend [] where
duplicated = init . tails
#ifdef MIN_VERSION_tagged
instance Extend (Tagged a) where
duplicated = Tagged
#endif
#if defined(MIN_VERSION_tagged) || MIN_VERSION_base(4,7,0)
instance Extend Proxy where
duplicated _ = Proxy
extended _ _ = Proxy
#endif
instance Extend Maybe where
duplicated Nothing = Nothing
duplicated j = Just j
instance Extend (Either a) where
duplicated (Left a) = Left a
duplicated r = Right r
instance Extend ((,)e) where
duplicated p = (fst p, p)
instance Semigroup m => Extend ((->)m) where
duplicated f m = f . (<>) m
#ifdef MIN_VERSION_containers
instance Extend Seq where
duplicated l = Seq.take (Seq.length l) (Seq.tails l)
instance Extend Tree where
duplicated w@(Node _ as) = Node w (map duplicated as)
#endif
#ifdef MIN_VERSION_comonad
instance Extend w => Extend (EnvT e w) where
duplicated (EnvT e wa) = EnvT e (extended (EnvT e) wa)
instance Extend w => Extend (StoreT s w) where
duplicated (StoreT wf s) = StoreT (extended StoreT wf) s
extended f (StoreT wf s) = StoreT (extended (\wf' s' -> f (StoreT wf' s')) wf) s
instance (Extend w, Semigroup m) => Extend (TracedT m w) where
extended f = TracedT . extended (\wf m -> f (TracedT (fmap (. (<>) m) wf))) . runTracedT
#endif
instance Extend Identity where
duplicated = Identity
instance Extend w => Extend (IdentityT w) where
extended f (IdentityT m) = IdentityT (extended (f . IdentityT) m)
instance Extend NonEmpty where
extended f w@(~(_ :| aas)) =
f w :| case aas of
[] -> []
(a:as) -> toList (extended f (a :| as))
instance (Extend f, Extend g) => Extend (Functor.Sum f g) where
extended f (InL l) = InL (extended (f . InL) l)
extended f (InR r) = InR (extended (f . InR) r)
instance (Extend f, Extend g) => Extend (f :+: g) where
extended f (L1 l) = L1 (extended (f . L1) l)
extended f (R1 r) = R1 (extended (f . R1) r)
instance Extend Generics.U1 where
extended _ U1 = U1
instance Extend Generics.V1 where
#if __GLASGOW_HASKELL__ >= 708
extended _ e = case e of {}
#else
extended _ e = seq e undefined
#endif
instance Extend f => Extend (Generics.M1 i t f) where
extended f = M1 . extended (f . M1) . unM1
instance Extend Par1 where
extended f w@Par1{} = Par1 (f w)
instance Extend f => Extend (Rec1 f) where
extended f = Rec1 . extended (f . Rec1) . unRec1
instance Extend Monoid.Sum where
extended f w@Monoid.Sum{} = Monoid.Sum (f w)
instance Extend Monoid.Product where
extended f w@Monoid.Product{} = Monoid.Product (f w)
instance Extend Monoid.Dual where
extended f w@Monoid.Dual{} = Monoid.Dual (f w)
#if MIN_VERSION_base(4,8,0)
instance Extend f => Extend (Monoid.Alt f) where
extended f = Monoid.Alt . extended (f . Monoid.Alt) . Monoid.getAlt
#endif
instance Extend Semigroup.First where
extended f w@Semigroup.First{} = Semigroup.First (f w)
instance Extend Semigroup.Last where
extended f w@Semigroup.Last{} = Semigroup.Last (f w)
instance Extend Semigroup.Min where
extended f w@Semigroup.Min{} = Semigroup.Min (f w)
instance Extend Semigroup.Max where
extended f w@Semigroup.Max{} = Semigroup.Max (f w)