{-# LANGUAGE DefaultSignatures, FlexibleContexts, KindSignatures, MultiParamTypeClasses #-} {- | Module : System.JBI.Commands.Tagged Description : Support for the Tagged type Copyright : (c) Ivan Lazar Miljenovic License : MIT Maintainer : Ivan.Miljenovic@gmail.com -} module System.JBI.Tagged ( WithTagged (..) , stripTag , stripTags , tag -- * Re-export , Tagged (..) , proxy ) where import Data.Coerce (Coercible, coerce) import Data.Tagged -------------------------------------------------------------------------------- class WithTagged (g :: * -> *) where -- | Strip off type safety, run the function, put type safety back on. withTaggedF :: (Coercible a a', Coercible b b', Functor f) => (a' -> f (g b')) -> Tagged t a -> f (g (Tagged t b)) default withTaggedF :: ( Coercible a a', Coercible b b', Functor f , Coercible (g b') (g (Tagged t b)) , Coercible (g (Tagged t b)) (g b')) => (a' -> f (g b')) -> Tagged t a -> f (g (Tagged t b)) withTaggedF f = fmap coerce . f . coerce tagInner :: Tagged t (g a) -> g (Tagged t a) default tagInner :: ( Coercible (Tagged t (g a)) (g (Tagged t a)) , Coercible (g (Tagged t a)) (g a)) => Tagged t (g a) -> g (Tagged t a) tagInner = coerce tagOuter :: g (Tagged t a) -> Tagged t (g a) default tagOuter :: (Coercible (g (Tagged t a)) (Tagged t (g a))) => g (Tagged t a) -> Tagged t (g a) tagOuter = coerce instance WithTagged Maybe instance WithTagged [] -- | Remove the tag along with (potentially) any newtype wrappers -- added on. stripTag :: (Coercible a a') => Tagged t a -> a' stripTag = coerce stripTags :: (Coercible a a') => [Tagged t a] -> [a'] stripTags = coerce -- | Put the appropriate tag on. tag :: (Coercible a a') => a -> Tagged t a' tag = coerce