module Data.Pair where

import Data.Functor.Rep
import Data.Distributive
import Data.Profunctor

data Pair a = Pair a a
  deriving (Int -> Pair a -> ShowS
[Pair a] -> ShowS
Pair a -> String
(Int -> Pair a -> ShowS)
-> (Pair a -> String) -> ([Pair a] -> ShowS) -> Show (Pair a)
forall a. Show a => Int -> Pair a -> ShowS
forall a. Show a => [Pair a] -> ShowS
forall a. Show a => Pair a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Pair a] -> ShowS
$cshowList :: forall a. Show a => [Pair a] -> ShowS
show :: Pair a -> String
$cshow :: forall a. Show a => Pair a -> String
showsPrec :: Int -> Pair a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Pair a -> ShowS
Show, Pair a -> Pair a -> Bool
(Pair a -> Pair a -> Bool)
-> (Pair a -> Pair a -> Bool) -> Eq (Pair a)
forall a. Eq a => Pair a -> Pair a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Pair a -> Pair a -> Bool
$c/= :: forall a. Eq a => Pair a -> Pair a -> Bool
== :: Pair a -> Pair a -> Bool
$c== :: forall a. Eq a => Pair a -> Pair a -> Bool
Eq, Eq (Pair a)
Eq (Pair a) =>
(Pair a -> Pair a -> Ordering)
-> (Pair a -> Pair a -> Bool)
-> (Pair a -> Pair a -> Bool)
-> (Pair a -> Pair a -> Bool)
-> (Pair a -> Pair a -> Bool)
-> (Pair a -> Pair a -> Pair a)
-> (Pair a -> Pair a -> Pair a)
-> Ord (Pair a)
Pair a -> Pair a -> Bool
Pair a -> Pair a -> Ordering
Pair a -> Pair a -> Pair a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Pair a)
forall a. Ord a => Pair a -> Pair a -> Bool
forall a. Ord a => Pair a -> Pair a -> Ordering
forall a. Ord a => Pair a -> Pair a -> Pair a
min :: Pair a -> Pair a -> Pair a
$cmin :: forall a. Ord a => Pair a -> Pair a -> Pair a
max :: Pair a -> Pair a -> Pair a
$cmax :: forall a. Ord a => Pair a -> Pair a -> Pair a
>= :: Pair a -> Pair a -> Bool
$c>= :: forall a. Ord a => Pair a -> Pair a -> Bool
> :: Pair a -> Pair a -> Bool
$c> :: forall a. Ord a => Pair a -> Pair a -> Bool
<= :: Pair a -> Pair a -> Bool
$c<= :: forall a. Ord a => Pair a -> Pair a -> Bool
< :: Pair a -> Pair a -> Bool
$c< :: forall a. Ord a => Pair a -> Pair a -> Bool
compare :: Pair a -> Pair a -> Ordering
$ccompare :: forall a. Ord a => Pair a -> Pair a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Pair a)
Ord, a -> Pair b -> Pair a
(a -> b) -> Pair a -> Pair b
(forall a b. (a -> b) -> Pair a -> Pair b)
-> (forall a b. a -> Pair b -> Pair a) -> Functor Pair
forall a b. a -> Pair b -> Pair a
forall a b. (a -> b) -> Pair a -> Pair b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Pair b -> Pair a
$c<$ :: forall a b. a -> Pair b -> Pair a
fmap :: (a -> b) -> Pair a -> Pair b
$cfmap :: forall a b. (a -> b) -> Pair a -> Pair b
Functor)

instance Applicative Pair where
  pure :: a -> Pair a
pure a :: a
a = a -> a -> Pair a
forall a. a -> a -> Pair a
Pair a
a a
a
  Pair f :: a -> b
f f' :: a -> b
f' <*> :: Pair (a -> b) -> Pair a -> Pair b
<*> Pair a :: a
a a' :: a
a' = b -> b -> Pair b
forall a. a -> a -> Pair a
Pair (a -> b
f a
a) (a -> b
f' a
a')

instance Distributive Pair where
  distribute :: f (Pair a) -> Pair (f a)
distribute = f (Pair a) -> Pair (f a)
forall (f :: * -> *) (w :: * -> *) a.
(Representable f, Functor w) =>
w (f a) -> f (w a)
distributeRep

instance Representable Pair where
  type Rep Pair = Bool
  tabulate :: (Rep Pair -> a) -> Pair a
tabulate f :: Rep Pair -> a
f = a -> a -> Pair a
forall a. a -> a -> Pair a
Pair (Rep Pair -> a
f Bool
Rep Pair
False) (Rep Pair -> a
f Bool
Rep Pair
True)
  index :: Pair a -> Rep Pair -> a
index (Pair a :: a
a _) False = a
a
  index (Pair _ b :: a
b) True = a
b

paired :: Profunctor p => p (Pair a) (Pair b) -> p (a, a) (b, b)
paired :: p (Pair a) (Pair b) -> p (a, a) (b, b)
paired = ((a, a) -> Pair a)
-> (Pair b -> (b, b)) -> p (Pair a) (Pair b) -> p (a, a) (b, b)
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap (\(a :: a
a, a' :: a
a') -> a -> a -> Pair a
forall a. a -> a -> Pair a
Pair a
a a
a') (\(Pair a :: b
a a' :: b
a') -> (b
a, b
a'))

liftPair :: (a -> a -> b) -> Pair a -> b
liftPair :: (a -> a -> b) -> Pair a -> b
liftPair f :: a -> a -> b
f (Pair a :: a
a a' :: a
a') = a -> a -> b
f a
a a
a'