{-# 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) -- | A left-strict pair; the base functor for streams of individual elements. 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