{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Both where
import Control.Applicative
import Control.Monad
import Data.Data
import Data.Foldable
import Data.Maybe
import Data.Monoid hiding ((<>))
import Data.Semigroup
import Data.Traversable
import Data.Zero
import GHC.Generics
newtype Both a = Both { getBoth :: Maybe a }
deriving (Eq, Ord, Read, Show, Data, Typeable, Generic, Generic1, Functor, Applicative, Alternative, Monad, MonadPlus, Foldable, Traversable)
instance Semigroup a => Semigroup (Both a) where
Both (Just x) <> Both (Just y) = Both . Just $ x <> y
_ <> _ = Both Nothing
instance (Monoid a, Semigroup a) => Monoid (Both a) where
mempty = Both $ Just mempty
mappend = (<>)
instance Semigroup a => Zero (Both a) where
zero = Both Nothing
both :: b -> (a -> b) -> Both a -> b
both z f = maybe z f . getBoth
fromBoth :: a -> Both a -> a
fromBoth z = fromMaybe z . getBoth