-- | Various utilities for working with newtype wrappers. module Data.Semiring.Newtype where import Data.Coerce import Text.Read import Text.Read.Lex -- import Text.ParserCombinators.ReadPrec -- import Control.Monad -------------------------------------------------------------------------------- -- Show1, Read1 -------------------------------------------------------------------------------- -- | 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 #-} -------------------------------------------------------------------------------- -- Typealiases to make coercion signatures shorter -------------------------------------------------------------------------------- type Binary a = a -> a -> a type CoerceBinary a b = Binary a -> Binary b type WrapBinary f a = Binary a -> BinaryWrapped f a type BinaryWrapped f a = Binary (f a) -------------------------------------------------------------------------------- -- Coercive composition -------------------------------------------------------------------------------- infixr 9 #. (#.) :: Coercible b c => (b -> c) -> (a -> b) -> a -> c (#.) _ = coerce {-# INLINE (#.) #-} infixr 9 .# (.#) :: Coercible a b => (b -> c) -> (a -> b) -> a -> c (.#) f _ = coerce f {-# INLINE (.#) #-}