strict-tuple-0.1.5: src/Data/Tuple/Strict/T2.hs
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StrictData #-}
module Data.Tuple.Strict.T2
( T2 (..),
sfst,
ssnd,
scurry,
suncurry,
sswap,
)
where
import Control.DeepSeq (NFData, rnf)
import Data.Biapplicative
import Data.Bifoldable
import Data.Bitraversable
import Data.Functor.Classes (Eq1 (liftEq), Eq2 (liftEq2))
import Data.Hashable (Hashable, hash, hashWithSalt)
import Data.Hashable.Lifted
( Hashable1,
Hashable2,
defaultLiftHashWithSalt,
hashWithSalt1,
liftHashWithSalt,
liftHashWithSalt2,
)
import Data.Semigroup
import GHC.Generics (Generic)
data T2 a b
= T2 a b
deriving stock (Bounded, Eq, Ord, Read, Show, Generic)
-- | @since 0.1.3
deriving stock instance Foldable (T2 a)
-- | @since 0.1.3
deriving stock instance Functor (T2 a)
-- | @since 0.1.3
deriving stock instance Traversable (T2 a)
-- | @since 0.1.5
instance Eq a => Eq1 (T2 a) where
liftEq = liftEq2 (==)
-- | @since 0.1.5
instance Eq2 T2 where
liftEq2 e1 e2 (T2 a b) (T2 a' b') =
e1 a a' && e2 b b'
-- | @since 0.1.3
instance Monoid a => Applicative (T2 a) where
pure b = T2 mempty b
T2 a f <*> T2 a' b = T2 (a <> a') (f b)
-- | @since 0.1.3
instance Monoid a => Monad (T2 a) where
return = pure
T2 a b >>= f = case f b of
T2 a' b' -> T2 (a <> a') b'
instance (Hashable a, Hashable b) => Hashable (T2 a b) where
hash (T2 a b) = hash a `hashWithSalt` b
hashWithSalt = hashWithSalt1
instance Hashable a => Hashable1 (T2 a) where
liftHashWithSalt = defaultLiftHashWithSalt
instance Hashable2 T2 where
liftHashWithSalt2 h1 h2 slt (T2 a b) = slt `h1` a `h2` b
instance (Monoid a, Monoid b) => Monoid (T2 a b) where
mempty = T2 mempty mempty
-- | @since 0.1.4
instance (NFData a, NFData b) => NFData (T2 a b) where
rnf (T2 a b) = rnf a `seq` rnf b
instance (Semigroup a, Semigroup b) => Semigroup (T2 a b) where
T2 a1 b1 <> T2 a2 b2 = T2 (a1 <> a2) (b1 <> b2)
stimes ii (T2 a b) = T2 (stimes ii a) (stimes ii b)
-- | @since 0.1.3
instance Bifunctor T2 where
bimap f g (T2 a b) = T2 (f a) (g b)
-- | @since 0.1.3
instance Biapplicative T2 where
bipure = T2
T2 f g <<*>> T2 a b = T2 (f a) (g b)
-- | @since 0.1.3
instance Bifoldable T2 where
bifoldMap f g (T2 a b) = f a <> g b
-- | @since 0.1.3
instance Bitraversable T2 where
bitraverse f g (T2 a b) = T2 <$> f a <*> g b
-- | A strict, 'T2'-based analog to 'fst'
--
-- @since 0.1.3
sfst :: T2 a b -> a
sfst (T2 a _) = a
-- | A strict, 'T2'-based analog to 'snd'
--
-- @since 0.1.3
ssnd :: T2 a b -> b
ssnd (T2 _ b) = b
-- | A strict, 'T2'-based analog to 'curry'
--
-- @since 0.1.3
scurry :: (T2 a b -> c) -> a -> b -> c
scurry f a b = f (T2 a b)
-- | A strict, 'T2'-based analog to 'uncurry'
--
-- @since 0.1.3
suncurry :: (a -> b -> c) -> T2 a b -> c
suncurry f (T2 a b) = f a b
-- | A strict, 'T2'-based analog to 'swap'
--
-- @since 0.1.3
sswap :: T2 a b -> T2 b a
sswap (T2 a b) = T2 b a