{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE TypeOperators #-}

module Data.Bifunctor.Linear.Internal.Bifunctor
  ( Bifunctor(..)
  ) where

import Prelude.Linear


-- | The Bifunctor class
--
-- == Laws
--
-- If 'bimap' is supplied, then
-- @'bimap' 'id' 'id' = 'id'@
--
-- * If 'first' and 'second' are supplied, then
-- @
-- 'first' 'id' ≡ 'id'
-- 'second' 'id' ≡ 'id'
-- @
--
-- * If all are supplied, then
-- @'bimap' f g = 'first' f '.' 'second' g
class Bifunctor p where
  {-# MINIMAL bimap | (first , second) #-}
  bimap :: (a %1-> b) -> (c %1-> d) -> a `p` c %1-> b `p` d
  bimap a %1 -> b
f c %1 -> d
g p a c
x = (a %1 -> b) -> p a d %1 -> p b d
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a %1 -> b) -> p a c %1 -> p b c
first a %1 -> b
f ((c %1 -> d) -> p a c %1 -> p a d
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b %1 -> c) -> p a b %1 -> p a c
second c %1 -> d
g p a c
x)
  {-# INLINE bimap #-}

  first :: (a %1-> b) -> a `p` c %1-> b `p` c
  first a %1 -> b
f = (a %1 -> b) -> (c %1 -> c) -> p a c %1 -> p b c
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a %1 -> b) -> (c %1 -> d) -> p a c %1 -> p b d
bimap a %1 -> b
f c %1 -> c
forall a. a %1 -> a
id
  {-# INLINE first #-}

  second :: (b %1-> c) -> a `p` b %1-> a `p` c
  second = (a %1 -> a) -> (b %1 -> c) -> p a b %1 -> p a c
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a %1 -> b) -> (c %1 -> d) -> p a c %1 -> p b d
bimap a %1 -> a
forall a. a %1 -> a
id
  {-# INLINE second #-}


-- # Instances
-------------------------------------------------------------------------------

instance Bifunctor (,) where
  bimap :: forall a b c d. (a %1 -> b) -> (c %1 -> d) -> (a, c) %1 -> (b, d)
bimap a %1 -> b
f c %1 -> d
g (a
x,c
y) = (a %1 -> b
f a
x, c %1 -> d
g c
y)
  first :: forall a b c. (a %1 -> b) -> (a, c) %1 -> (b, c)
first a %1 -> b
f (a
x,c
y) = (a %1 -> b
f a
x, c
y)
  second :: forall b c a. (b %1 -> c) -> (a, b) %1 -> (a, c)
second b %1 -> c
g (a
x,b
y) = (a
x, b %1 -> c
g b
y)

instance Bifunctor Either where
  bimap :: forall a b c d.
(a %1 -> b) -> (c %1 -> d) -> Either a c %1 -> Either b d
bimap a %1 -> b
f c %1 -> d
g = (a %1 -> Either b d)
-> (c %1 -> Either b d) -> Either a c %1 -> Either b d
forall a c b. (a %1 -> c) -> (b %1 -> c) -> Either a b %1 -> c
either (b %1 -> Either b d
forall a b. a -> Either a b
Left (b %1 -> Either b d) %1 -> (a %1 -> b) %1 -> a %1 -> Either b d
forall b c a. (b %1 -> c) %1 -> (a %1 -> b) %1 -> a %1 -> c
. a %1 -> b
f) (d %1 -> Either b d
forall a b. b -> Either a b
Right (d %1 -> Either b d) %1 -> (c %1 -> d) %1 -> c %1 -> Either b d
forall b c a. (b %1 -> c) %1 -> (a %1 -> b) %1 -> a %1 -> c
. c %1 -> d
g)