-- |
-- Module      : Basement.These
-- License     : BSD-style
-- Maintainer  : Nicolas Di Prima <[email protected]>
-- Stability   : stable
-- Portability : portable
--
-- @These a b@, sum type to represent either @a@ or @b@ or both.
--
module Basement.These
    ( These(..)
    ) where

import Basement.Compat.Base
import Basement.NormalForm
import Basement.Compat.Bifunctor

-- | Either a or b or both.
data These a b
    = This a
    | That b
    | These a b
  deriving (Eq, Ord, Show, Typeable)

instance (NormalForm a, NormalForm b) => NormalForm (These a b) where
    toNormalForm (This a) = toNormalForm a
    toNormalForm (That b) = toNormalForm b
    toNormalForm (These a b) = toNormalForm a `seq` toNormalForm b

instance Bifunctor These where
    bimap fa _  (This a)    = This  (fa a)
    bimap _  fb (That b)    = That  (fb b)
    bimap fa fb (These a b) = These (fa a) (fb b)

instance Functor (These a) where
    fmap = second