module Lens.Family.Phantom where

import Control.Applicative.Backwards (Backwards(..))
import Control.Applicative (Const(..))
import Data.Functor.Constant (Constant(..))
import Data.Functor.Compose (Compose(..))

class Functor f => Phantom f where
  coerce :: f a -> f b

instance Phantom f => Phantom (Backwards f) where
  coerce :: forall a b. Backwards f a -> Backwards f b
coerce (Backwards f a
x) = f b -> Backwards f b
forall {k} (f :: k -> *) (a :: k). f a -> Backwards f a
Backwards (f a -> f b
forall a b. f a -> f b
forall (f :: * -> *) a b. Phantom f => f a -> f b
coerce f a
x)

instance Phantom (Const a) where
  coerce :: forall a b. Const a a -> Const a b
coerce (Const a
x) = (a -> Const a b
forall {k} a (b :: k). a -> Const a b
Const a
x)

instance Phantom (Constant a) where
  coerce :: forall a b. Constant a a -> Constant a b
coerce (Constant a
x) = (a -> Constant a b
forall {k} a (b :: k). a -> Constant a b
Constant a
x)

instance (Phantom f, Functor g) => Phantom (Compose f g) where
  coerce :: forall a b. Compose f g a -> Compose f g b
coerce (Compose f (g a)
x) = f (g b) -> Compose f g b
forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (f (g a) -> f (g b)
forall a b. f a -> f b
forall (f :: * -> *) a b. Phantom f => f a -> f b
coerce f (g a)
x)