{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ >= 706
{-# LANGUAGE PolyKinds #-}
#endif
#if __GLASGOW_HASKELL__ >= 800
{-# LANGUAGE TypeInType #-}
#endif
module Control.Lens.Equality
(
Equality, Equality'
, AnEquality, AnEquality'
, (:~:)(..)
, runEq
, substEq
, mapEq
, fromEq
, simply
, simple
, equality
, equality'
, withEquality
, underEquality
, overEquality
, fromLeibniz
, fromLeibniz'
, cloneEquality
, Identical(..)
) where
import Control.Lens.Type
import Data.Proxy (Proxy)
import Data.Type.Equality ((:~:)(..))
#if __GLASGOW_HASKELL__ >= 800
import GHC.Exts (TYPE)
import Data.Kind (Type)
#endif
#ifdef HLINT
{-# ANN module "HLint: ignore Use id" #-}
{-# ANN module "HLint: ignore Eta reduce" #-}
#endif
#include "lens-common.h"
data Identical a b s t where
Identical :: Identical a b a b
#if __GLASGOW_HASKELL__ >= 706
type AnEquality (s :: k1) (t :: k2) (a :: k1) (b :: k2) = Identical a (Proxy b) a (Proxy b) -> Identical a (Proxy b) s (Proxy t)
#else
type AnEquality s t a b = Identical a (Proxy b) a (Proxy b) -> Identical a (Proxy b) s (Proxy t)
#endif
type AnEquality' s a = AnEquality s s a a
runEq :: AnEquality s t a b -> Identical s t a b
runEq l = case l Identical of Identical -> Identical
{-# INLINE runEq #-}
#if __GLASGOW_HASKELL__ >= 800
substEq :: forall s t a b rep (r :: TYPE rep).
AnEquality s t a b -> ((s ~ a, t ~ b) => r) -> r
#else
substEq :: AnEquality s t a b -> ((s ~ a, t ~ b) => r) -> r
#endif
substEq l = case runEq l of
Identical -> \r -> r
{-# INLINE substEq #-}
#if __GLASGOW_HASKELL__ >= 800
mapEq :: forall k1 k2 (s :: k1) (t :: k2) (a :: k1) (b :: k2) (f :: k1 -> Type) . AnEquality s t a b -> f s -> f a
#elif __GLASGOW_HASKELL__ >= 706
mapEq :: forall (s :: k1) (t :: k2) (a :: k1) (b :: k2) (f :: k1 -> *) . AnEquality s t a b -> f s -> f a
#else
mapEq :: AnEquality s t a b -> f s -> f a
#endif
mapEq l r = substEq l r
{-# INLINE mapEq #-}
fromEq :: AnEquality s t a b -> Equality b a t s
fromEq l = substEq l id
{-# INLINE fromEq #-}
#if __GLASGOW_HASKELL__ >= 800
simply :: forall p f s a rep (r :: TYPE rep).
(Optic' p f s a -> r) -> Optic' p f s a -> r
#else
simply :: (Optic' p f s a -> r) -> Optic' p f s a -> r
#endif
simply = id
{-# INLINE simply #-}
simple :: Equality' a a
simple = id
{-# INLINE simple #-}
cloneEquality :: AnEquality s t a b -> Equality s t a b
cloneEquality an = substEq an id
{-# INLINE cloneEquality #-}
equality :: s :~: a -> b :~: t -> Equality s t a b
equality Refl Refl = id
{-# INLINE equality #-}
equality' :: a :~: b -> Equality' a b
equality' Refl = id
{-# INLINE equality' #-}
overEquality :: AnEquality s t a b -> p a b -> p s t
overEquality an = substEq an id
{-# INLINE overEquality #-}
underEquality :: AnEquality s t a b -> p t s -> p b a
underEquality an = substEq an id
{-# INLINE underEquality #-}
fromLeibniz :: (Identical a b a b -> Identical a b s t) -> Equality s t a b
fromLeibniz f = case f Identical of Identical -> id
{-# INLINE fromLeibniz #-}
fromLeibniz' :: (s :~: s -> s :~: a) -> Equality' s a
fromLeibniz' f = case f Refl of Refl -> id
{-# INLINE fromLeibniz' #-}
#if __GLASGOW_HASKELL__ >= 800
withEquality :: forall s t a b rep (r :: TYPE rep).
AnEquality s t a b -> (s :~: a -> b :~: t -> r) -> r
#else
withEquality :: forall s t a b r.
AnEquality s t a b -> (s :~: a -> b :~: t -> r) -> r
#endif
withEquality an = substEq an (\f -> f Refl Refl)
{-# INLINE withEquality #-}