{-# LANGUAGE CPP, DeriveDataTypeable, DeriveTraversable, DeriveFoldable,
DeriveGeneric #-}
module Data.Functor.Of (Of(..)) where
import Data.Monoid (Monoid (..))
import Data.Semigroup (Semigroup (..))
import Control.Applicative
import Data.Traversable (Traversable)
import Data.Foldable (Foldable)
import Data.Bifunctor
import Data.Data
#if MIN_VERSION_base(4,9,0)
import Data.Functor.Classes
import Data.Foldable (Foldable)
import Data.Traversable (Traversable)
#endif
import GHC.Generics (Generic, Generic1)
data Of a b = !a :> b
deriving (Data, Eq, Foldable, Ord,
Read, Show, Traversable, Typeable, Generic, Generic1)
infixr 5 :>
instance (Semigroup a, Semigroup b) => Semigroup (Of a b) where
(m :> w) <> (m' :> w') = (m <> m') :> (w <> w')
{-#INLINE (<>) #-}
instance (Monoid a, Monoid b) => Monoid (Of a b) where
mempty = mempty :> mempty
{-#INLINE mempty #-}
#if !(MIN_VERSION_base(4,11,0))
mappend (m :> w) (m' :> w') = mappend m m' :> mappend w w'
{-#INLINE mappend #-}
#endif
instance Functor (Of a) where
fmap f (a :> x) = a :> f x
{-#INLINE fmap #-}
a <$ (b :> _) = b :> a
{-#INLINE (<$) #-}
#if MIN_VERSION_base(4,8,0)
instance Bifunctor Of where
bimap f g (a :> b) = f a :> g b
{-#INLINE bimap #-}
first f (a :> b) = f a :> b
{-#INLINE first #-}
second g (a :> b) = a :> g b
{-#INLINE second #-}
#endif
instance Monoid a => Applicative (Of a) where
pure x = mempty :> x
{-#INLINE pure #-}
(m :> f) <*> (m' :> x) = mappend m m' :> f x
{-#INLINE (<*>) #-}
(m :> _) *> (m' :> y) = mappend m m' :> y
{-#INLINE (*>) #-}
(m :> x) <* (m' :> _) = mappend m m' :> x
{-#INLINE (<*) #-}
instance Monoid a => Monad (Of a) where
return = pure
{-#INLINE return #-}
(m :> _) >> (m' :> y) = mappend m m' :> y
{-#INLINE (>>) #-}
(m :> x) >>= f = let m' :> y = f x in mappend m m' :> y
{-#INLINE (>>=) #-}
#if MIN_VERSION_base(4,9,0)
instance Show a => Show1 (Of a) where
liftShowsPrec = liftShowsPrec2 showsPrec showList
instance Eq a => Eq1 (Of a) where
liftEq = liftEq2 (==)
instance Ord a => Ord1 (Of a) where
liftCompare = liftCompare2 compare
instance Show2 Of where
liftShowsPrec2 spa _sla spb _slb p (a :> b) =
showParen (p > 5) $
spa 6 a .
showString " :> " .
spb 6 b
instance Eq2 Of where
liftEq2 f g (x :> y) (z :> w) = f x z && g y w
instance Ord2 Of where
liftCompare2 comp1 comp2 (x :> y) (z :> w) =
comp1 x z `mappend` comp2 y w
#endif