{-# LANGUAGE NoMonomorphismRestriction #-}
module Data.Functor.Utils (module Data.Functor.Utils, module X) where
import Prelude hiding ((.))
import GHC.Exts (Constraint)
import Data.Traversable (mapM)
import Data.Functor.Compose as X (Compose(Compose), getCompose)
import Control.Lens
type family Functors lst :: Constraint where
Functors '[] = ()
Functors (f ': fs) = (Functor f, Functors fs)
type family Applicatives lst :: Constraint where
Applicatives '[] = ()
Applicatives (f ': fs) = (Applicative f, Applicatives fs)
fmap0 :: (a -> b) -> a -> b
(.) , (∘) :: Functor f1 => (a -> b) -> f1 a -> f1 b
fmap2, (.:) , (<<$>>) , (∘∘) :: Functors '[f1,f2] => (a -> b) -> f2 (f1 a) -> f2 (f1 b)
fmap3, (.:.) , (<<<$>>>) , (∘∘∘) :: Functors '[f1,f2,f3] => (a -> b) -> f3 (f2 (f1 a)) -> f3 (f2 (f1 b))
fmap4, (.::) , (<<<<$>>>>) , (∘∘∘∘) :: Functors '[f1,f2,f3,f4] => (a -> b) -> f4 (f3 (f2 (f1 a))) -> f4 (f3 (f2 (f1 b)))
fmap5, (.::.), (<<<<<$>>>>>) , (∘∘∘∘∘) :: Functors '[f1,f2,f3,f4,f5] => (a -> b) -> f5 (f4 (f3 (f2 (f1 a)))) -> f5 (f4 (f3 (f2 (f1 b))))
fmap0 = ($) ; {-# INLINE fmap0 #-}
fmap1 = fmap ; {-# INLINE fmap1 #-}
fmap2 = fmap.fmap ; {-# INLINE fmap2 #-}
fmap3 = fmap.fmap2 ; {-# INLINE fmap3 #-}
fmap4 = fmap.fmap3 ; {-# INLINE fmap4 #-}
fmap5 = fmap.fmap4 ; {-# INLINE fmap5 #-}
infixr 9 .
infixr 8 .:
infixr 8 .:.
infixr 8 .::
infixr 8 .::.
(.) = fmap ; {-# INLINE (.) #-}
(.:) = fmap2 ; {-# INLINE (.:) #-}
(.:.) = fmap3 ; {-# INLINE (.:.) #-}
(.::) = fmap4 ; {-# INLINE (.::) #-}
(.::.) = fmap5 ; {-# INLINE (.::.) #-}
infixr 9 ∘
infixr 8 ∘∘
infixr 8 ∘∘∘
infixr 8 ∘∘∘∘
infixr 8 ∘∘∘∘∘
(∘) = fmap ; {-# INLINE (∘) #-}
(∘∘) = fmap2 ; {-# INLINE (∘∘) #-}
(∘∘∘) = fmap3 ; {-# INLINE (∘∘∘) #-}
(∘∘∘∘) = fmap4 ; {-# INLINE (∘∘∘∘) #-}
(∘∘∘∘∘) = fmap5 ; {-# INLINE (∘∘∘∘∘) #-}
infixl 4 <<$>>
infixl 4 <<<$>>>
infixl 4 <<<<$>>>>
infixl 4 <<<<<$>>>>>
(<<$>>) = fmap2 ; {-# INLINE (<<$>>) #-}
(<<<$>>>) = fmap3 ; {-# INLINE (<<<$>>>) #-}
(<<<<$>>>>) = fmap4 ; {-# INLINE (<<<<$>>>>) #-}
(<<<<<$>>>>>) = fmap5 ; {-# INLINE (<<<<<$>>>>>) #-}
infixl 4 <<*>>
infixl 4 <<<*>>>
infixl 4 <<<<*>>>>
infixl 4 <<<<<*>>>>>
(<<*>>) :: Applicatives '[f1, f2] => f2 (f1 (a -> b)) -> f2 (f1 a) -> f2 (f1 b)
(<<<*>>>) :: Applicatives '[f1, f2, f3] => f3 (f2 (f1 (a -> b))) -> f3 (f2 (f1 a)) -> f3 (f2 (f1 b))
(<<<<*>>>>) :: Applicatives '[f1, f2, f3, f4] => f4 (f3 (f2 (f1 (a -> b)))) -> f4 (f3 (f2 (f1 a))) -> f4 (f3 (f2 (f1 b)))
(<<<<<*>>>>>) :: Applicatives '[f1, f2, f3, f4, f5] => f5 (f4 (f3 (f2 (f1 (a -> b))))) -> f5 (f4 (f3 (f2 (f1 a)))) -> f5 (f4 (f3 (f2 (f1 b))))
(<<*>>) = (<*>) . fmap (<*>) ; {-# INLINE (<<*>>) #-}
(<<<*>>>) = (<*>) . fmap (<<*>>) ; {-# INLINE (<<<*>>>) #-}
(<<<<*>>>>) = (<*>) . fmap (<<<*>>>) ; {-# INLINE (<<<<*>>>>) #-}
(<<<<<*>>>>>) = (<*>) . fmap (<<<<*>>>>) ; {-# INLINE (<<<<<*>>>>>) #-}
infixl 4 |$
infixl 4 $|
(|$) :: (a -> b) -> a -> (a, b)
($|) :: (a -> b) -> a -> (b, a)
f |$ a = (a, f a) ; {-# INLINE (|$) #-}
f $| a = (f a, a) ; {-# INLINE ($|) #-}
infixl 4 <|$>
infixl 4 <$|>
(<|$>) :: Functor f => (a -> b) -> f a -> f (a, b)
(<$|>) :: Functor f => (a -> b) -> f a -> f (b, a)
f <|$> a = (f |$) <$> a ; {-# INLINE (<|$>) #-}
f <$|> a = (f $|) <$> a ; {-# INLINE (<$|>) #-}
composed :: Iso' (f (g a)) (Compose f g a)
composed = iso Compose getCompose ; {-# INLINE composed #-}
nested l f = getCompose . l (fmap Compose f) ; {-# INLINE nested #-}