module Unison.Merge.TwoWayI
  ( TwoWayI (..),
    forgetBoth,
    who_,
  )
where

import Control.Lens (Lens')
import Data.Semialign (Semialign, alignWith)
import Data.Semigroup.Generic (GenericSemigroupMonoid (..))
import Data.These (These (..))
import Data.Zip (Zip, zipWith)
import Unison.Merge.EitherWayI (EitherWayI (..))
import Unison.Merge.TwoWay (TwoWay (..))
import Unison.Prelude
import Prelude hiding (zipWith)

-- | "Two-way inclusive".
data TwoWayI a = TwoWayI
  { forall a. TwoWayI a -> a
alice :: a,
    forall a. TwoWayI a -> a
bob :: a,
    forall a. TwoWayI a -> a
both :: a
  }
  deriving stock ((forall m. Monoid m => TwoWayI m -> m)
-> (forall m a. Monoid m => (a -> m) -> TwoWayI a -> m)
-> (forall m a. Monoid m => (a -> m) -> TwoWayI a -> m)
-> (forall a b. (a -> b -> b) -> b -> TwoWayI a -> b)
-> (forall a b. (a -> b -> b) -> b -> TwoWayI a -> b)
-> (forall b a. (b -> a -> b) -> b -> TwoWayI a -> b)
-> (forall b a. (b -> a -> b) -> b -> TwoWayI a -> b)
-> (forall a. (a -> a -> a) -> TwoWayI a -> a)
-> (forall a. (a -> a -> a) -> TwoWayI a -> a)
-> (forall a. TwoWayI a -> [a])
-> (forall a. TwoWayI a -> Bool)
-> (forall a. TwoWayI a -> Int)
-> (forall a. Eq a => a -> TwoWayI a -> Bool)
-> (forall a. Ord a => TwoWayI a -> a)
-> (forall a. Ord a => TwoWayI a -> a)
-> (forall a. Num a => TwoWayI a -> a)
-> (forall a. Num a => TwoWayI a -> a)
-> Foldable TwoWayI
forall a. Eq a => a -> TwoWayI a -> Bool
forall a. Num a => TwoWayI a -> a
forall a. Ord a => TwoWayI a -> a
forall m. Monoid m => TwoWayI m -> m
forall a. TwoWayI a -> Bool
forall a. TwoWayI a -> Int
forall a. TwoWayI a -> [a]
forall a. (a -> a -> a) -> TwoWayI a -> a
forall m a. Monoid m => (a -> m) -> TwoWayI a -> m
forall b a. (b -> a -> b) -> b -> TwoWayI a -> b
forall a b. (a -> b -> b) -> b -> TwoWayI a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => TwoWayI m -> m
fold :: forall m. Monoid m => TwoWayI m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> TwoWayI a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> TwoWayI a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> TwoWayI a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> TwoWayI a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> TwoWayI a -> b
foldr :: forall a b. (a -> b -> b) -> b -> TwoWayI a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> TwoWayI a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> TwoWayI a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> TwoWayI a -> b
foldl :: forall b a. (b -> a -> b) -> b -> TwoWayI a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> TwoWayI a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> TwoWayI a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> TwoWayI a -> a
foldr1 :: forall a. (a -> a -> a) -> TwoWayI a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> TwoWayI a -> a
foldl1 :: forall a. (a -> a -> a) -> TwoWayI a -> a
$ctoList :: forall a. TwoWayI a -> [a]
toList :: forall a. TwoWayI a -> [a]
$cnull :: forall a. TwoWayI a -> Bool
null :: forall a. TwoWayI a -> Bool
$clength :: forall a. TwoWayI a -> Int
length :: forall a. TwoWayI a -> Int
$celem :: forall a. Eq a => a -> TwoWayI a -> Bool
elem :: forall a. Eq a => a -> TwoWayI a -> Bool
$cmaximum :: forall a. Ord a => TwoWayI a -> a
maximum :: forall a. Ord a => TwoWayI a -> a
$cminimum :: forall a. Ord a => TwoWayI a -> a
minimum :: forall a. Ord a => TwoWayI a -> a
$csum :: forall a. Num a => TwoWayI a -> a
sum :: forall a. Num a => TwoWayI a -> a
$cproduct :: forall a. Num a => TwoWayI a -> a
product :: forall a. Num a => TwoWayI a -> a
Foldable, (forall a b. (a -> b) -> TwoWayI a -> TwoWayI b)
-> (forall a b. a -> TwoWayI b -> TwoWayI a) -> Functor TwoWayI
forall a b. a -> TwoWayI b -> TwoWayI a
forall a b. (a -> b) -> TwoWayI a -> TwoWayI b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> TwoWayI a -> TwoWayI b
fmap :: forall a b. (a -> b) -> TwoWayI a -> TwoWayI b
$c<$ :: forall a b. a -> TwoWayI b -> TwoWayI a
<$ :: forall a b. a -> TwoWayI b -> TwoWayI a
Functor, (forall x. TwoWayI a -> Rep (TwoWayI a) x)
-> (forall x. Rep (TwoWayI a) x -> TwoWayI a)
-> Generic (TwoWayI a)
forall x. Rep (TwoWayI a) x -> TwoWayI a
forall x. TwoWayI a -> Rep (TwoWayI a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (TwoWayI a) x -> TwoWayI a
forall a x. TwoWayI a -> Rep (TwoWayI a) x
$cfrom :: forall a x. TwoWayI a -> Rep (TwoWayI a) x
from :: forall x. TwoWayI a -> Rep (TwoWayI a) x
$cto :: forall a x. Rep (TwoWayI a) x -> TwoWayI a
to :: forall x. Rep (TwoWayI a) x -> TwoWayI a
Generic)
  deriving (Semigroup (TwoWayI a)
TwoWayI a
Semigroup (TwoWayI a) =>
TwoWayI a
-> (TwoWayI a -> TwoWayI a -> TwoWayI a)
-> ([TwoWayI a] -> TwoWayI a)
-> Monoid (TwoWayI a)
[TwoWayI a] -> TwoWayI a
TwoWayI a -> TwoWayI a -> TwoWayI a
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall a. Monoid a => Semigroup (TwoWayI a)
forall a. Monoid a => TwoWayI a
forall a. Monoid a => [TwoWayI a] -> TwoWayI a
forall a. Monoid a => TwoWayI a -> TwoWayI a -> TwoWayI a
$cmempty :: forall a. Monoid a => TwoWayI a
mempty :: TwoWayI a
$cmappend :: forall a. Monoid a => TwoWayI a -> TwoWayI a -> TwoWayI a
mappend :: TwoWayI a -> TwoWayI a -> TwoWayI a
$cmconcat :: forall a. Monoid a => [TwoWayI a] -> TwoWayI a
mconcat :: [TwoWayI a] -> TwoWayI a
Monoid, NonEmpty (TwoWayI a) -> TwoWayI a
TwoWayI a -> TwoWayI a -> TwoWayI a
(TwoWayI a -> TwoWayI a -> TwoWayI a)
-> (NonEmpty (TwoWayI a) -> TwoWayI a)
-> (forall b. Integral b => b -> TwoWayI a -> TwoWayI a)
-> Semigroup (TwoWayI a)
forall b. Integral b => b -> TwoWayI a -> TwoWayI a
forall a. Semigroup a => NonEmpty (TwoWayI a) -> TwoWayI a
forall a. Semigroup a => TwoWayI a -> TwoWayI a -> TwoWayI a
forall a b.
(Semigroup a, Integral b) =>
b -> TwoWayI a -> TwoWayI a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: forall a. Semigroup a => TwoWayI a -> TwoWayI a -> TwoWayI a
<> :: TwoWayI a -> TwoWayI a -> TwoWayI a
$csconcat :: forall a. Semigroup a => NonEmpty (TwoWayI a) -> TwoWayI a
sconcat :: NonEmpty (TwoWayI a) -> TwoWayI a
$cstimes :: forall a b.
(Semigroup a, Integral b) =>
b -> TwoWayI a -> TwoWayI a
stimes :: forall b. Integral b => b -> TwoWayI a -> TwoWayI a
Semigroup) via (GenericSemigroupMonoid (TwoWayI a))

instance Applicative TwoWayI where
  pure :: forall a. a -> TwoWayI a
pure a
x = a -> a -> a -> TwoWayI a
forall a. a -> a -> a -> TwoWayI a
TwoWayI a
x a
x a
x
  TwoWayI a -> b
f a -> b
g a -> b
h <*> :: forall a b. TwoWayI (a -> b) -> TwoWayI a -> TwoWayI b
<*> TwoWayI a
x a
y a
z = b -> b -> b -> TwoWayI b
forall a. a -> a -> a -> TwoWayI a
TwoWayI (a -> b
f a
x) (a -> b
g a
y) (a -> b
h a
z)

instance Semialign TwoWayI where
  alignWith :: (These a b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
  alignWith :: forall a b c.
(These a b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
alignWith These a b -> c
f =
    (a -> b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
forall a b c. (a -> b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
forall (f :: * -> *) a b c.
Zip f =>
(a -> b -> c) -> f a -> f b -> f c
zipWith \a
x b
y -> These a b -> c
f (a -> b -> These a b
forall a b. a -> b -> These a b
These a
x b
y)

instance Zip TwoWayI where
  zipWith :: (a -> b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
  zipWith :: forall a b c. (a -> b -> c) -> TwoWayI a -> TwoWayI b -> TwoWayI c
zipWith a -> b -> c
f (TwoWayI a
x1 a
x2 a
x3) (TwoWayI b
y1 b
y2 b
y3) =
    c -> c -> c -> TwoWayI c
forall a. a -> a -> a -> TwoWayI a
TwoWayI (a -> b -> c
f a
x1 b
y1) (a -> b -> c
f a
x2 b
y2) (a -> b -> c
f a
x3 b
y3)

forgetBoth :: TwoWayI a -> TwoWay a
forgetBoth :: forall a. TwoWayI a -> TwoWay a
forgetBoth TwoWayI {a
$sel:alice:TwoWayI :: forall a. TwoWayI a -> a
alice :: a
alice, a
$sel:bob:TwoWayI :: forall a. TwoWayI a -> a
bob :: a
bob} =
  TwoWay {a
alice :: a
$sel:alice:TwoWay :: a
alice, a
bob :: a
$sel:bob:TwoWay :: a
bob}

who_ :: EitherWayI x -> Lens' (TwoWayI a) a
who_ :: forall x a. EitherWayI x -> Lens' (TwoWayI a) a
who_ = \case
  OnlyAlice x
_ -> (a -> f a) -> TwoWayI a -> f (TwoWayI a)
#alice
  OnlyBob x
_ -> (a -> f a) -> TwoWayI a -> f (TwoWayI a)
#bob
  AliceAndBob x
_ -> (a -> f a) -> TwoWayI a -> f (TwoWayI a)
#both