{-# LANGUAGE QuantifiedConstraints #-} module Blanks.NatNewtype ( NatNewtype , natNewtypeFrom , natNewtypeTo ) where import Data.Coerce (Coercible, coerce) import Data.Kind (Type) -- | A "natural isomorphism" between two functors, like exists -- derivably between newtyped functors and their wrapped types. -- The functional dependency requires that 'g' be the newtype -- and 'm' the wrapped type. class ( forall a. Coercible (m a) (g a) , forall a. Coercible (g a) (m a) )=> NatNewtype (m :: Type -> Type) (g :: Type -> Type) | g -> m -- | Coerce from the wrapped type to the newtype. natNewtypeTo :: NatNewtype m g => m a -> g a natNewtypeTo = coerce {-# INLINE natNewtypeTo #-} -- | Coerce from the newtype to the wrapped type. natNewtypeFrom :: NatNewtype m g => g a -> m a natNewtypeFrom = coerce {-# INLINE natNewtypeFrom #-}