{-# OPTIONS_HADDOCK not-home #-}

module Bluefin.Internal.OneWayCoercible
  ( module Bluefin.Internal.OneWayCoercible,
    Generic,
  )
where

import Data.Coerce (Coercible, coerce)
import Data.Type.Coercion (Coercion (Coercion))
import GHC.Generics
import Unsafe.Coerce (unsafeCoerce)

gOneWayCoercion ::
  forall a b. (GOneWayCoercible (Rep a) (Rep b)) => OneWayCoercion a b
gOneWayCoercion :: forall a b. GOneWayCoercible (Rep a) (Rep b) => OneWayCoercion a b
gOneWayCoercion = OneWayCoercion a b
forall {k} (a :: k) (b :: k). OneWayCoercion a b
unsafeOneWayCoercion

gOneWayCoercible ::
  (GOneWayCoercible (Rep (h e)) (Rep (h es))) =>
  -- | ͘
  OneWayCoercibleD (h e) (h es)
gOneWayCoercible :: forall {k} (h :: k -> *) (e :: k) (es :: k).
GOneWayCoercible (Rep (h e)) (Rep (h es)) =>
OneWayCoercibleD (h e) (h es)
gOneWayCoercible = OneWayCoercion (h e) (h es) -> OneWayCoercibleD (h e) (h es)
forall {k} (a :: k) (b :: k).
OneWayCoercion a b -> OneWayCoercibleD a b
MkOneWayCoercibleD OneWayCoercion (h e) (h es)
forall a b. GOneWayCoercible (Rep a) (Rep b) => OneWayCoercion a b
gOneWayCoercion

gOneWayCoercible2 ::
  (GOneWayCoercible (Rep (h e e')) (Rep (h es es'))) =>
  OneWayCoercibleD (h e e') (h es es')
gOneWayCoercible2 :: forall {k} {k} (h :: k -> k -> *) (e :: k) (e' :: k) (es :: k)
       (es' :: k).
GOneWayCoercible (Rep (h e e')) (Rep (h es es')) =>
OneWayCoercibleD (h e e') (h es es')
gOneWayCoercible2 = OneWayCoercion (h e e') (h es es')
-> OneWayCoercibleD (h e e') (h es es')
forall {k} (a :: k) (b :: k).
OneWayCoercion a b -> OneWayCoercibleD a b
MkOneWayCoercibleD OneWayCoercion (h e e') (h es es')
forall a b. GOneWayCoercible (Rep a) (Rep b) => OneWayCoercion a b
gOneWayCoercion

oneWayCoercible :: (Coercible a b) => OneWayCoercibleD a b
oneWayCoercible :: forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible = OneWayCoercion a b -> OneWayCoercibleD a b
forall {k} (a :: k) (b :: k).
OneWayCoercion a b -> OneWayCoercibleD a b
MkOneWayCoercibleD (Coercion a b -> OneWayCoercion a b
forall {k} (a :: k) (b :: k). Coercion a b -> OneWayCoercion a b
MkOneWayCoercion Coercion a b
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion)

unsafeOneWayCoercion :: forall a b. OneWayCoercion a b
unsafeOneWayCoercion :: forall {k} (a :: k) (b :: k). OneWayCoercion a b
unsafeOneWayCoercion = Coercion a b -> OneWayCoercion a b
forall {k} (a :: k) (b :: k). Coercion a b -> OneWayCoercion a b
MkOneWayCoercion (Coercion a a -> Coercion a b
forall a b. a -> b
unsafeCoerce (forall (a :: k) (b :: k). Coercible a b => Coercion a b
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion @a @a))

unsafeOneWayCoercible :: forall a b. OneWayCoercibleD a b
unsafeOneWayCoercible :: forall {k} (a :: k) (b :: k). OneWayCoercibleD a b
unsafeOneWayCoercible = OneWayCoercion a b -> OneWayCoercibleD a b
forall {k} (a :: k) (b :: k).
OneWayCoercion a b -> OneWayCoercibleD a b
MkOneWayCoercibleD OneWayCoercion a b
forall {k} (a :: k) (b :: k). OneWayCoercion a b
unsafeOneWayCoercion

newtype OneWayCoercion a b = MkOneWayCoercion (Coercion a b)

newtype OneWayCoercibleD a b = MkOneWayCoercibleD (OneWayCoercion a b)

oneWayCoercion :: (OneWayCoercible a b) => OneWayCoercion a b
oneWayCoercion :: forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercion a b
oneWayCoercion = case OneWayCoercibleD a b
forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercibleD a b
oneWayCoercibleImpl of
  MkOneWayCoercibleD OneWayCoercion a b
oneWay -> OneWayCoercion a b
oneWay

oneWayCoerce :: forall a b. (OneWayCoercible a b) => a -> b
oneWayCoerce :: forall a b. OneWayCoercible a b => a -> b
oneWayCoerce = OneWayCoercion a b -> a -> b
forall a b. OneWayCoercion a b -> a -> b
oneWayCoerceWith (forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercion a b
forall a b. OneWayCoercible a b => OneWayCoercion a b
oneWayCoercion @a @b)

oneWayCoerceWith :: OneWayCoercion a b -> a -> b
oneWayCoerceWith :: forall a b. OneWayCoercion a b -> a -> b
oneWayCoerceWith (MkOneWayCoercion Coercion a b
Coercion) = a -> b
forall a b. Coercible a b => a -> b
coerce

unsafeCoercionOfOneWayCoercion :: OneWayCoercion a b -> Coercion a b
unsafeCoercionOfOneWayCoercion :: forall {k} (a :: k) (b :: k). OneWayCoercion a b -> Coercion a b
unsafeCoercionOfOneWayCoercion (MkOneWayCoercion Coercion a b
c) = Coercion a b
c

unsafeCoercionOfOneWayCoercible ::
  forall a b. (OneWayCoercible a b) => Coercion a b
unsafeCoercionOfOneWayCoercible :: forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible = case forall (a :: k) (b :: k). OneWayCoercible a b => OneWayCoercion a b
forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercion a b
oneWayCoercion @a @b of
  MkOneWayCoercion Coercion a b
c -> Coercion a b
c

class OneWayCoercible a b where
  oneWayCoercibleImpl :: OneWayCoercibleD a b

instance {-# INCOHERENT #-} OneWayCoercible s s where
  oneWayCoercibleImpl :: OneWayCoercibleD s s
oneWayCoercibleImpl = OneWayCoercibleD s s
forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible

instance OneWayCoercible () () where
  oneWayCoercibleImpl :: OneWayCoercibleD () ()
oneWayCoercibleImpl = OneWayCoercibleD () ()
forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible

instance
  (OneWayCoercible a1 a2) =>
  OneWayCoercible (Maybe a1) (Maybe a2)
  where
  oneWayCoercibleImpl :: OneWayCoercibleD (Maybe a1) (Maybe a2)
oneWayCoercibleImpl = case forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
forall a b. OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible @a1 @a2 of
    Coercion a1 a2
Coercion -> OneWayCoercibleD (Maybe a1) (Maybe a2)
forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible

instance
  (OneWayCoercible a1 a2, OneWayCoercible b1 b2) =>
  OneWayCoercible (Either a1 b1) (Either a2 b2)
  where
  oneWayCoercibleImpl :: OneWayCoercibleD (Either a1 b1) (Either a2 b2)
oneWayCoercibleImpl = case forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
forall a b. OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible @a1 @a2 of
    Coercion a1 a2
Coercion -> case forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
forall a b. OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible @b1 @b2 of
      Coercion b1 b2
Coercion -> OneWayCoercibleD (Either a1 b1) (Either a2 b2)
forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible

-- | Other sizes of tuples follow this pattern. We will add them when
-- someone needs them.
instance
  (OneWayCoercible a1 a2, OneWayCoercible b1 b2) =>
  OneWayCoercible (a1, b1) (a2, b2)
  where
  oneWayCoercibleImpl :: OneWayCoercibleD (a1, b1) (a2, b2)
oneWayCoercibleImpl = case forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
forall a b. OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible @a1 @a2 of
    Coercion a1 a2
Coercion -> case forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
forall a b. OneWayCoercible a b => Coercion a b
unsafeCoercionOfOneWayCoercible @b1 @b2 of
      Coercion b1 b2
Coercion -> OneWayCoercibleD (a1, b1) (a2, b2)
forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
oneWayCoercible

trans :: OneWayCoercion a b -> OneWayCoercion b c -> OneWayCoercion a c
trans :: forall {k} (a :: k) (b :: k) (c :: k).
OneWayCoercion a b -> OneWayCoercion b c -> OneWayCoercion a c
trans OneWayCoercion a b
c1 OneWayCoercion b c
c2 = case OneWayCoercion a b -> Coercion a b
forall {k} (a :: k) (b :: k). OneWayCoercion a b -> Coercion a b
unsafeCoercionOfOneWayCoercion OneWayCoercion a b
c1 of
  Coercion a b
Coercion -> case OneWayCoercion b c -> Coercion b c
forall {k} (a :: k) (b :: k). OneWayCoercion a b -> Coercion a b
unsafeCoercionOfOneWayCoercion OneWayCoercion b c
c2 of
    Coercion b c
Coercion -> Coercion a c -> OneWayCoercion a c
forall {k} (a :: k) (b :: k). Coercion a b -> OneWayCoercion a b
MkOneWayCoercion Coercion a c
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion

class GOneWayCoercible a b

instance GOneWayCoercible U1 U1

instance
  (OneWayCoercible c c') =>
  GOneWayCoercible (K1 i c) (K1 i' c')

instance
  (GOneWayCoercible f f') =>
  GOneWayCoercible (M1 i t f) (M1 i' t' f')

instance
  (GOneWayCoercible f f', GOneWayCoercible g g') =>
  GOneWayCoercible (f :*: g) (f' :*: g')

instance
  (OneWayCoercible a a', OneWayCoercible b b') =>
  OneWayCoercible (a' -> b) (a -> b')
  where
  oneWayCoercibleImpl :: OneWayCoercibleD (a' -> b) (a -> b')
oneWayCoercibleImpl = case forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercion a b
forall a b. OneWayCoercible a b => OneWayCoercion a b
oneWayCoercion @a @a' of
    MkOneWayCoercion Coercion a a'
Coercion -> case forall {k} (a :: k) (b :: k).
OneWayCoercible a b =>
OneWayCoercion a b
forall a b. OneWayCoercible a b => OneWayCoercion a b
oneWayCoercion @b @b' of
      MkOneWayCoercion Coercion b b'
Coercion ->
        OneWayCoercion (a' -> b) (a -> b')
-> OneWayCoercibleD (a' -> b) (a -> b')
forall {k} (a :: k) (b :: k).
OneWayCoercion a b -> OneWayCoercibleD a b
MkOneWayCoercibleD (Coercion (a' -> b) (a -> b') -> OneWayCoercion (a' -> b) (a -> b')
forall {k} (a :: k) (b :: k). Coercion a b -> OneWayCoercion a b
MkOneWayCoercion Coercion (a' -> b) (a -> b')
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion)