module Data.Coerce.Util ( -- * Function coercion utils (#.) , (.#) -- * Shorten coercion type signatures , Binary , CoerceBinary , WrapBinary , WrappedBinary -- * Newtype utils , showsNewtype , readsNewtype ) where import Data.Coerce import Text.Read import Text.Read.Lex -- | A definition for 'Data.Functor.Classes.liftShowsPrec', -- suitable for newtypes. -- -- Given a newtype declared as: -- -- @newtype T a = T { unT :: a }@ -- -- The 'Data.Functor.Classes.Show1' definition can be given as: -- -- @ -- instance Show1 T where -- liftShowsPrec = showsNewtype "T" "unT" -- @ showsNewtype :: Coercible b a => String -> String -> (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> b -> ShowS showsNewtype cons acc = s where s sp _ n x = showParen (n > 10) $ showString cons . showString " {" . showString acc . showString " = " . sp 0 (coerce x) . showChar '}' {-# INLINE showsNewtype #-} -- | A definition for 'Data.Functor.Classes.liftReadsPrec', -- suitable for newtypes. -- -- Given a newtype declared as: -- -- @ -- newtype T a = T { unT :: a } -- @ -- -- The 'Data.Functor.Classes.Read1' definition can be given as: -- -- @ -- instance Read1 T where -- liftReadsPrec = readsNewtype "T" "unT" -- @ readsNewtype :: Coercible a b => String -> String -> (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS b readsNewtype cons acc = r where r rp _ = readPrec_to_S $ parens $ prec 10 $ do lift $ expect (Ident cons) Punc "{" <- lexP lift $ expect (Ident acc) Punc "=" <- lexP x <- reset (readS_to_Prec rp) Punc "}" <- lexP pure (coerce x) {-# INLINE readsNewtype #-} type Binary a = a -> a -> a type CoerceBinary a b = Binary a -> Binary b type WrapBinary f a = Binary a -> WrappedBinary f a type WrappedBinary f a = Binary (f a) -- | Coercive left-composition. infixr 9 #. (#.) :: Coercible b c => (b -> c) -> (a -> b) -> a -> c (#.) _ = coerce {-# INLINE (#.) #-} -- | Coercive right-composition. infixr 9 .# (.#) :: Coercible a b => (b -> c) -> (a -> b) -> a -> c (.#) f _ = coerce f {-# INLINE (.#) #-}