{-# LANGUAGE CPP #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE UndecidableInstances #-}

{- |
  Compatibility copypasta from the future to derive Applicative without
  incurring dependency and boilerplate from "Distributive"/"Representable".
-}
module Resource.Collection.Generic
  ( Generic1(..)
  , Generically1(..)
  ) where

import RIO

import Control.Applicative (Alternative(..))
import Data.Kind (Type)
import GHC.Generics

#if !MIN_VERSION_base(4,17,0)

type    Generically1 :: forall k. (k -> Type) -> (k -> Type)
newtype Generically1 f a where
#if MIN_VERSION_base(4,16,0)
  -- Generically1 :: forall {k} f a. f a -> Generically1 @k f a
#endif
  Generically1 :: f a -> Generically1 f a

-- | @since 4.17.0.0
instance (Generic1 f, Functor (Rep1 f)) => Functor (Generically1 f) where
  fmap :: (a -> a') -> (Generically1 f a -> Generically1 f a')
  fmap :: forall a b. (a -> b) -> Generically1 f a -> Generically1 f b
fmap a -> a'
f (Generically1 f a
as) = f a' -> Generically1 f a'
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a' -> f a'
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 ((a -> a') -> Rep1 f a -> Rep1 f a'
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a'
f (f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
as)))

  (<$) :: a -> Generically1 f b -> Generically1 f a
  a
a <$ :: forall a b. a -> Generically1 f b -> Generically1 f a
<$ Generically1 f b
as = f a -> Generically1 f a
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (a
a a -> Rep1 f b -> Rep1 f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f b -> Rep1 f b
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f b
as))

-- | @since 4.17.0.0
instance (Generic1 f, Applicative (Rep1 f)) => Applicative (Generically1 f) where
  pure :: a -> Generically1 f a
  pure :: forall a. a -> Generically1 f a
pure a
a = f a -> Generically1 f a
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (a -> Rep1 f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a))

  (<*>) :: Generically1 f (a1 -> a2) -> Generically1 f a1 -> Generically1 f a2
  Generically1 f (a1 -> a2)
fs <*> :: forall a b.
Generically1 f (a -> b) -> Generically1 f a -> Generically1 f b
<*> Generically1 f a1
as = f a2 -> Generically1 f a2
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a2 -> f a2
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (f (a1 -> a2) -> Rep1 f (a1 -> a2)
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f (a1 -> a2)
fs Rep1 f (a1 -> a2) -> Rep1 f a1 -> Rep1 f a2
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f a1 -> Rep1 f a1
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a1
as))

  liftA2 :: (a1 -> a2 -> a3)
         -> (Generically1 f a1 -> Generically1 f a2 -> Generically1 f a3)
  liftA2 :: forall a b c.
(a -> b -> c)
-> Generically1 f a -> Generically1 f b -> Generically1 f c
liftA2 a1 -> a2 -> a3
(·) (Generically1 f a1
as) (Generically1 f a2
bs) = f a3 -> Generically1 f a3
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a3 -> f a3
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 ((a1 -> a2 -> a3) -> Rep1 f a1 -> Rep1 f a2 -> Rep1 f a3
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a1 -> a2 -> a3
(·) (f a1 -> Rep1 f a1
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a1
as) (f a2 -> Rep1 f a2
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a2
bs)))

-- | @since 4.17.0.0
instance (Generic1 f, Alternative (Rep1 f)) => Alternative (Generically1 f) where
  empty :: Generically1 f a
  empty :: forall a. Generically1 f a
empty = f a -> Generically1 f a
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 Rep1 f a
forall (f :: * -> *) a. Alternative f => f a
empty)

  (<|>) :: Generically1 f a -> Generically1 f a -> Generically1 f a
  Generically1 f a
as1 <|> :: forall a. Generically1 f a -> Generically1 f a -> Generically1 f a
<|> Generically1 f a
as2 = f a -> Generically1 f a
forall {k} (f :: k -> *) (a :: k). f a -> Generically1 f a
Generically1
    (Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
as1 Rep1 f a -> Rep1 f a -> Rep1 f a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
as2))

#endif