{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Functor.Product -- Copyright : (c) Ross Paterson 2010 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : portable -- -- Products, lifted to functors. -- -- @since 4.9.0.0 ----------------------------------------------------------------------------- module Data.Functor.Product ( Product(..), ) where import Control.Applicative import Control.Monad (MonadPlus(..)) import Control.Monad.Fix (MonadFix(..)) import Control.Monad.Zip (MonadZip(mzipWith)) import Data.Data (Data) import Data.Foldable (Foldable(foldMap)) import Data.Functor.Classes import Data.Monoid (mappend) import Data.Traversable (Traversable(traverse)) import GHC.Generics (Generic, Generic1) import Text.Read (Read(..), readListDefault, readListPrecDefault) -- | Lifted product of functors. data Product f g a = Pair (f a) (g a) deriving (Data, Generic, Generic1) -- | @since 4.9.0.0 instance (Eq1 f, Eq1 g) => Eq1 (Product f g) where liftEq eq (Pair x1 y1) (Pair x2 y2) = liftEq eq x1 x2 && liftEq eq y1 y2 -- | @since 4.9.0.0 instance (Ord1 f, Ord1 g) => Ord1 (Product f g) where liftCompare comp (Pair x1 y1) (Pair x2 y2) = liftCompare comp x1 x2 `mappend` liftCompare comp y1 y2 -- | @since 4.9.0.0 instance (Read1 f, Read1 g) => Read1 (Product f g) where liftReadPrec rp rl = readData $ readBinaryWith (liftReadPrec rp rl) (liftReadPrec rp rl) "Pair" Pair liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance (Show1 f, Show1 g) => Show1 (Product f g) where liftShowsPrec sp sl d (Pair x y) = showsBinaryWith (liftShowsPrec sp sl) (liftShowsPrec sp sl) "Pair" d x y -- | @since 4.9.0.0 instance (Eq1 f, Eq1 g, Eq a) => Eq (Product f g a) where (==) = eq1 -- | @since 4.9.0.0 instance (Ord1 f, Ord1 g, Ord a) => Ord (Product f g a) where compare = compare1 -- | @since 4.9.0.0 instance (Read1 f, Read1 g, Read a) => Read (Product f g a) where readPrec = readPrec1 readListPrec = readListPrecDefault readList = readListDefault -- | @since 4.9.0.0 instance (Show1 f, Show1 g, Show a) => Show (Product f g a) where showsPrec = showsPrec1 -- | @since 4.9.0.0 instance (Functor f, Functor g) => Functor (Product f g) where fmap f (Pair x y) = Pair (fmap f x) (fmap f y) -- | @since 4.9.0.0 instance (Foldable f, Foldable g) => Foldable (Product f g) where foldMap f (Pair x y) = foldMap f x `mappend` foldMap f y -- | @since 4.9.0.0 instance (Traversable f, Traversable g) => Traversable (Product f g) where traverse f (Pair x y) = liftA2 Pair (traverse f x) (traverse f y) -- | @since 4.9.0.0 instance (Applicative f, Applicative g) => Applicative (Product f g) where pure x = Pair (pure x) (pure x) Pair f g <*> Pair x y = Pair (f <*> x) (g <*> y) liftA2 f (Pair a b) (Pair x y) = Pair (liftA2 f a x) (liftA2 f b y) -- | @since 4.9.0.0 instance (Alternative f, Alternative g) => Alternative (Product f g) where empty = Pair empty empty Pair x1 y1 <|> Pair x2 y2 = Pair (x1 <|> x2) (y1 <|> y2) -- | @since 4.9.0.0 instance (Monad f, Monad g) => Monad (Product f g) where Pair m n >>= f = Pair (m >>= fstP . f) (n >>= sndP . f) where fstP (Pair a _) = a sndP (Pair _ b) = b -- | @since 4.9.0.0 instance (MonadPlus f, MonadPlus g) => MonadPlus (Product f g) where mzero = Pair mzero mzero Pair x1 y1 `mplus` Pair x2 y2 = Pair (x1 `mplus` x2) (y1 `mplus` y2) -- | @since 4.9.0.0 instance (MonadFix f, MonadFix g) => MonadFix (Product f g) where mfix f = Pair (mfix (fstP . f)) (mfix (sndP . f)) where fstP (Pair a _) = a sndP (Pair _ b) = b -- | @since 4.9.0.0 instance (MonadZip f, MonadZip g) => MonadZip (Product f g) where mzipWith f (Pair x1 y1) (Pair x2 y2) = Pair (mzipWith f x1 x2) (mzipWith f y1 y2)