{-# LANGUAGE UndecidableInstances #-} -- due to type class design
{-# LANGUAGE AllowAmbiguousTypes  #-} -- due to type class design

module Generic.Data.Function.Contra.NonSum where

import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divisible

import GHC.Generics
import Generic.Data.Function.Contra.Constructor
import Generic.Data.Function.Common.Error
import Generic.Data.Function.Common.Generic

class GContraNonSum tag gf where gContraNonSum :: GenericContraF tag (gf p)

instance (Contravariant (GenericContraF tag), GContraNonSumD tag gf)
  => GContraNonSum tag (C1 c gf) where
    gContraNonSum :: forall (p :: k). GenericContraF tag (C1 c gf p)
gContraNonSum = (M1 C c gf p -> gf p)
-> GenericContraF tag (gf p) -> GenericContraF tag (M1 C c gf p)
forall a' a.
(a' -> a) -> GenericContraF tag a -> GenericContraF tag a'
forall (f :: Type -> Type) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap M1 C c gf p -> gf p
forall k i (c :: Meta) (f :: k -> Type) (p :: k). M1 i c f p -> f p
unM1 (forall (tag :: k) (gf :: k -> Type) (p :: k).
GContraNonSumD tag gf =>
GenericContraF tag (gf p)
forall {k} {k} (tag :: k) (gf :: k -> Type) (p :: k).
GContraNonSumD tag gf =>
GenericContraF tag (gf p)
gContraNonSumD @tag)

class GContraNonSumD tag gf where gContraNonSumD :: GenericContraF tag (gf p)

instance (Contravariant (GenericContraF tag), GContraC tag gf)
  => GContraNonSumD tag (C1 c gf) where
    gContraNonSumD :: forall (p :: k). GenericContraF tag (C1 c gf p)
gContraNonSumD = (M1 C c gf p -> gf p)
-> GenericContraF tag (gf p) -> GenericContraF tag (M1 C c gf p)
forall a' a.
(a' -> a) -> GenericContraF tag a -> GenericContraF tag a'
forall (f :: Type -> Type) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap M1 C c gf p -> gf p
forall k i (c :: Meta) (f :: k -> Type) (p :: k). M1 i c f p -> f p
unM1 (forall (tag :: k) (gf :: k -> Type) (p :: k).
GContraC tag gf =>
GenericContraF tag (gf p)
forall {k} {k1} (tag :: k) (gf :: k1 -> Type) (p :: k1).
GContraC tag gf =>
GenericContraF tag (gf p)
gContraC @tag)

instance GContraNonSumD tag (l :+: r) where gContraNonSumD :: forall (p :: k). GenericContraF tag ((:+:) l r p)
gContraNonSumD = [Char] -> GenericContraF tag ((:+:) l r p)
forall a. HasCallStack => [Char] -> a
error [Char]
eNoSum

instance Divisible (GenericContraF tag) => GContraNonSumD tag V1 where
    gContraNonSumD :: forall (p :: k). GenericContraF tag (V1 p)
gContraNonSumD = (V1 p -> Any)
-> GenericContraF tag Any -> GenericContraF tag (V1 p)
forall a' a.
(a' -> a) -> GenericContraF tag a -> GenericContraF tag a'
forall (f :: Type -> Type) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap V1 p -> Any
forall {k} (x :: k) a. V1 x -> a
absurdV1 GenericContraF tag Any
forall a. GenericContraF tag a
forall (f :: Type -> Type) a. Divisible f => f a
conquer