{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Functor.Classes -- Copyright : (c) Ross Paterson 2013 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : [email protected] -- Stability : experimental -- Portability : portable -- -- Liftings of the Prelude classes 'Eq', 'Ord', 'Read' and 'Show' to -- unary and binary type constructors. -- -- These classes are needed to express the constraints on arguments of -- transformers in portable Haskell. Thus for a new transformer @T@, -- one might write instances like -- -- > instance (Eq1 f) => Eq1 (T f) where ... -- > instance (Ord1 f) => Ord1 (T f) where ... -- > instance (Read1 f) => Read1 (T f) where ... -- > instance (Show1 f) => Show1 (T f) where ... -- -- If these instances can be defined, defining instances of the base -- classes is mechanical: -- -- > instance (Eq1 f, Eq a) => Eq (T f a) where (==) = eq1 -- > instance (Ord1 f, Ord a) => Ord (T f a) where compare = compare1 -- > instance (Read1 f, Read a) => Read (T f a) where -- > readPrec = readPrec1 -- > readListPrec = readListPrecDefault -- > instance (Show1 f, Show a) => Show (T f a) where showsPrec = showsPrec1 -- -- @since 4.9.0.0 ----------------------------------------------------------------------------- module Data.Functor.Classes ( -- * Liftings of Prelude classes -- ** For unary constructors Eq1(..), eq1, Ord1(..), compare1, Read1(..), readsPrec1, readPrec1, liftReadListDefault, liftReadListPrecDefault, Show1(..), showsPrec1, -- ** For binary constructors Eq2(..), eq2, Ord2(..), compare2, Read2(..), readsPrec2, readPrec2, liftReadList2Default, liftReadListPrec2Default, Show2(..), showsPrec2, -- * Helper functions -- $example readsData, readData, readsUnaryWith, readUnaryWith, readsBinaryWith, readBinaryWith, showsUnaryWith, showsBinaryWith, -- ** Obsolete helpers readsUnary, readsUnary1, readsBinary1, showsUnary, showsUnary1, showsBinary1, ) where import Control.Applicative (Alternative((<|>)), Const(Const)) import Data.Functor.Identity (Identity(Identity)) import Data.Proxy (Proxy(Proxy)) import Data.List.NonEmpty (NonEmpty(..)) import Data.Monoid (mappend) import GHC.Read (expectP, list, paren) import Text.ParserCombinators.ReadPrec (ReadPrec, readPrec_to_S, readS_to_Prec) import Text.Read (Read(..), parens, prec, step) import Text.Read.Lex (Lexeme(..)) import Text.Show (showListWith) -- | Lifting of the 'Eq' class to unary type constructors. -- -- @since 4.9.0.0 class Eq1 f where -- | Lift an equality test through the type constructor. -- -- The function will usually be applied to an equality function, -- but the more general type ensures that the implementation uses -- it to compare elements of the first container with elements of -- the second. -- -- @since 4.9.0.0 liftEq :: (a -> b -> Bool) -> f a -> f b -> Bool -- | Lift the standard @('==')@ function through the type constructor. -- -- @since 4.9.0.0 eq1 :: (Eq1 f, Eq a) => f a -> f a -> Bool eq1 = liftEq (==) -- | Lifting of the 'Ord' class to unary type constructors. -- -- @since 4.9.0.0 class (Eq1 f) => Ord1 f where -- | Lift a 'compare' function through the type constructor. -- -- The function will usually be applied to a comparison function, -- but the more general type ensures that the implementation uses -- it to compare elements of the first container with elements of -- the second. -- -- @since 4.9.0.0 liftCompare :: (a -> b -> Ordering) -> f a -> f b -> Ordering -- | Lift the standard 'compare' function through the type constructor. -- -- @since 4.9.0.0 compare1 :: (Ord1 f, Ord a) => f a -> f a -> Ordering compare1 = liftCompare compare -- | Lifting of the 'Read' class to unary type constructors. -- -- Both 'liftReadsPrec' and 'liftReadPrec' exist to match the interface -- provided in the 'Read' type class, but it is recommended to implement -- 'Read1' instances using 'liftReadPrec' as opposed to 'liftReadsPrec', since -- the former is more efficient than the latter. For example: -- -- @ -- instance 'Read1' T where -- 'liftReadPrec' = ... -- 'liftReadListPrec' = 'liftReadListPrecDefault' -- @ -- -- For more information, refer to the documentation for the 'Read' class. -- -- @since 4.9.0.0 class Read1 f where {-# MINIMAL liftReadsPrec | liftReadPrec #-} -- | 'readsPrec' function for an application of the type constructor -- based on 'readsPrec' and 'readList' functions for the argument type. -- -- @since 4.9.0.0 liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (f a) liftReadsPrec rp rl = readPrec_to_S $ liftReadPrec (readS_to_Prec rp) (readS_to_Prec (const rl)) -- | 'readList' function for an application of the type constructor -- based on 'readsPrec' and 'readList' functions for the argument type. -- The default implementation using standard list syntax is correct -- for most types. -- -- @since 4.9.0.0 liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [f a] liftReadList rp rl = readPrec_to_S (list $ liftReadPrec (readS_to_Prec rp) (readS_to_Prec (const rl))) 0 -- | 'readPrec' function for an application of the type constructor -- based on 'readPrec' and 'readListPrec' functions for the argument type. -- -- @since 4.10.0.0 liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (f a) liftReadPrec rp rl = readS_to_Prec $ liftReadsPrec (readPrec_to_S rp) (readPrec_to_S rl 0) -- | 'readListPrec' function for an application of the type constructor -- based on 'readPrec' and 'readListPrec' functions for the argument type. -- -- The default definition uses 'liftReadList'. Instances that define -- 'liftReadPrec' should also define 'liftReadListPrec' as -- 'liftReadListPrecDefault'. -- -- @since 4.10.0.0 liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [f a] liftReadListPrec rp rl = readS_to_Prec $ \_ -> liftReadList (readPrec_to_S rp) (readPrec_to_S rl 0) -- | Lift the standard 'readsPrec' and 'readList' functions through the -- type constructor. -- -- @since 4.9.0.0 readsPrec1 :: (Read1 f, Read a) => Int -> ReadS (f a) readsPrec1 = liftReadsPrec readsPrec readList -- | Lift the standard 'readPrec' and 'readListPrec' functions through the -- type constructor. -- -- @since 4.10.0.0 readPrec1 :: (Read1 f, Read a) => ReadPrec (f a) readPrec1 = liftReadPrec readPrec readListPrec -- | A possible replacement definition for the 'liftReadList' method. -- This is only needed for 'Read1' instances where 'liftReadListPrec' isn't -- defined as 'liftReadListPrecDefault'. -- -- @since 4.10.0.0 liftReadListDefault :: Read1 f => (Int -> ReadS a) -> ReadS [a] -> ReadS [f a] liftReadListDefault rp rl = readPrec_to_S (liftReadListPrec (readS_to_Prec rp) (readS_to_Prec (const rl))) 0 -- | A possible replacement definition for the 'liftReadListPrec' method, -- defined using 'liftReadPrec'. -- -- @since 4.10.0.0 liftReadListPrecDefault :: Read1 f => ReadPrec a -> ReadPrec [a] -> ReadPrec [f a] liftReadListPrecDefault rp rl = list (liftReadPrec rp rl) -- | Lifting of the 'Show' class to unary type constructors. -- -- @since 4.9.0.0 class Show1 f where -- | 'showsPrec' function for an application of the type constructor -- based on 'showsPrec' and 'showList' functions for the argument type. -- -- @since 4.9.0.0 liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> f a -> ShowS -- | 'showList' function for an application of the type constructor -- based on 'showsPrec' and 'showList' functions for the argument type. -- The default implementation using standard list syntax is correct -- for most types. -- -- @since 4.9.0.0 liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [f a] -> ShowS liftShowList sp sl = showListWith (liftShowsPrec sp sl 0) -- | Lift the standard 'showsPrec' and 'showList' functions through the -- type constructor. -- -- @since 4.9.0.0 showsPrec1 :: (Show1 f, Show a) => Int -> f a -> ShowS showsPrec1 = liftShowsPrec showsPrec showList -- | Lifting of the 'Eq' class to binary type constructors. -- -- @since 4.9.0.0 class Eq2 f where -- | Lift equality tests through the type constructor. -- -- The function will usually be applied to equality functions, -- but the more general type ensures that the implementation uses -- them to compare elements of the first container with elements of -- the second. -- -- @since 4.9.0.0 liftEq2 :: (a -> b -> Bool) -> (c -> d -> Bool) -> f a c -> f b d -> Bool -- | Lift the standard @('==')@ function through the type constructor. -- -- @since 4.9.0.0 eq2 :: (Eq2 f, Eq a, Eq b) => f a b -> f a b -> Bool eq2 = liftEq2 (==) (==) -- | Lifting of the 'Ord' class to binary type constructors. -- -- @since 4.9.0.0 class (Eq2 f) => Ord2 f where -- | Lift 'compare' functions through the type constructor. -- -- The function will usually be applied to comparison functions, -- but the more general type ensures that the implementation uses -- them to compare elements of the first container with elements of -- the second. -- -- @since 4.9.0.0 liftCompare2 :: (a -> b -> Ordering) -> (c -> d -> Ordering) -> f a c -> f b d -> Ordering -- | Lift the standard 'compare' function through the type constructor. -- -- @since 4.9.0.0 compare2 :: (Ord2 f, Ord a, Ord b) => f a b -> f a b -> Ordering compare2 = liftCompare2 compare compare -- | Lifting of the 'Read' class to binary type constructors. -- -- Both 'liftReadsPrec2' and 'liftReadPrec2' exist to match the interface -- provided in the 'Read' type class, but it is recommended to implement -- 'Read2' instances using 'liftReadPrec2' as opposed to 'liftReadsPrec2', -- since the former is more efficient than the latter. For example: -- -- @ -- instance 'Read2' T where -- 'liftReadPrec2' = ... -- 'liftReadListPrec2' = 'liftReadListPrec2Default' -- @ -- -- For more information, refer to the documentation for the 'Read' class. -- @since 4.9.0.0 class Read2 f where {-# MINIMAL liftReadsPrec2 | liftReadPrec2 #-} -- | 'readsPrec' function for an application of the type constructor -- based on 'readsPrec' and 'readList' functions for the argument types. -- -- @since 4.9.0.0 liftReadsPrec2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> Int -> ReadS (f a b) liftReadsPrec2 rp1 rl1 rp2 rl2 = readPrec_to_S $ liftReadPrec2 (readS_to_Prec rp1) (readS_to_Prec (const rl1)) (readS_to_Prec rp2) (readS_to_Prec (const rl2)) -- | 'readList' function for an application of the type constructor -- based on 'readsPrec' and 'readList' functions for the argument types. -- The default implementation using standard list syntax is correct -- for most types. -- -- @since 4.9.0.0 liftReadList2 :: (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] -> ReadS [f a b] liftReadList2 rp1 rl1 rp2 rl2 = readPrec_to_S (list $ liftReadPrec2 (readS_to_Prec rp1) (readS_to_Prec (const rl1)) (readS_to_Prec rp2) (readS_to_Prec (const rl2))) 0 -- | 'readPrec' function for an application of the type constructor -- based on 'readPrec' and 'readListPrec' functions for the argument types. -- -- @since 4.10.0.0 liftReadPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec (f a b) liftReadPrec2 rp1 rl1 rp2 rl2 = readS_to_Prec $ liftReadsPrec2 (readPrec_to_S rp1) (readPrec_to_S rl1 0) (readPrec_to_S rp2) (readPrec_to_S rl2 0) -- | 'readListPrec' function for an application of the type constructor -- based on 'readPrec' and 'readListPrec' functions for the argument types. -- -- The default definition uses 'liftReadList2'. Instances that define -- 'liftReadPrec2' should also define 'liftReadListPrec2' as -- 'liftReadListPrec2Default'. -- -- @since 4.10.0.0 liftReadListPrec2 :: ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec [f a b] liftReadListPrec2 rp1 rl1 rp2 rl2 = readS_to_Prec $ \_ -> liftReadList2 (readPrec_to_S rp1) (readPrec_to_S rl1 0) (readPrec_to_S rp2) (readPrec_to_S rl2 0) -- | Lift the standard 'readsPrec' function through the type constructor. -- -- @since 4.9.0.0 readsPrec2 :: (Read2 f, Read a, Read b) => Int -> ReadS (f a b) readsPrec2 = liftReadsPrec2 readsPrec readList readsPrec readList -- | Lift the standard 'readPrec' function through the type constructor. -- -- @since 4.10.0.0 readPrec2 :: (Read2 f, Read a, Read b) => ReadPrec (f a b) readPrec2 = liftReadPrec2 readPrec readListPrec readPrec readListPrec -- | A possible replacement definition for the 'liftReadList2' method. -- This is only needed for 'Read2' instances where 'liftReadListPrec2' isn't -- defined as 'liftReadListPrec2Default'. -- -- @since 4.10.0.0 liftReadList2Default :: Read2 f => (Int -> ReadS a) -> ReadS [a] -> (Int -> ReadS b) -> ReadS [b] ->ReadS [f a b] liftReadList2Default rp1 rl1 rp2 rl2 = readPrec_to_S (liftReadListPrec2 (readS_to_Prec rp1) (readS_to_Prec (const rl1)) (readS_to_Prec rp2) (readS_to_Prec (const rl2))) 0 -- | A possible replacement definition for the 'liftReadListPrec2' method, -- defined using 'liftReadPrec2'. -- -- @since 4.10.0.0 liftReadListPrec2Default :: Read2 f => ReadPrec a -> ReadPrec [a] -> ReadPrec b -> ReadPrec [b] -> ReadPrec [f a b] liftReadListPrec2Default rp1 rl1 rp2 rl2 = list (liftReadPrec2 rp1 rl1 rp2 rl2) -- | Lifting of the 'Show' class to binary type constructors. -- -- @since 4.9.0.0 class Show2 f where -- | 'showsPrec' function for an application of the type constructor -- based on 'showsPrec' and 'showList' functions for the argument types. -- -- @since 4.9.0.0 liftShowsPrec2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> Int -> f a b -> ShowS -- | 'showList' function for an application of the type constructor -- based on 'showsPrec' and 'showList' functions for the argument types. -- The default implementation using standard list syntax is correct -- for most types. -- -- @since 4.9.0.0 liftShowList2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> [f a b] -> ShowS liftShowList2 sp1 sl1 sp2 sl2 = showListWith (liftShowsPrec2 sp1 sl1 sp2 sl2 0) -- | Lift the standard 'showsPrec' function through the type constructor. -- -- @since 4.9.0.0 showsPrec2 :: (Show2 f, Show a, Show b) => Int -> f a b -> ShowS showsPrec2 = liftShowsPrec2 showsPrec showList showsPrec showList -- Instances for Prelude type constructors -- | @since 4.9.0.0 instance Eq1 Maybe where liftEq _ Nothing Nothing = True liftEq _ Nothing (Just _) = False liftEq _ (Just _) Nothing = False liftEq eq (Just x) (Just y) = eq x y -- | @since 4.9.0.0 instance Ord1 Maybe where liftCompare _ Nothing Nothing = EQ liftCompare _ Nothing (Just _) = LT liftCompare _ (Just _) Nothing = GT liftCompare comp (Just x) (Just y) = comp x y -- | @since 4.9.0.0 instance Read1 Maybe where liftReadPrec rp _ = parens (expectP (Ident "Nothing") *> pure Nothing) <|> readData (readUnaryWith rp "Just" Just) liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance Show1 Maybe where liftShowsPrec _ _ _ Nothing = showString "Nothing" liftShowsPrec sp _ d (Just x) = showsUnaryWith sp "Just" d x -- | @since 4.9.0.0 instance Eq1 [] where liftEq _ [] [] = True liftEq _ [] (_:_) = False liftEq _ (_:_) [] = False liftEq eq (x:xs) (y:ys) = eq x y && liftEq eq xs ys -- | @since 4.9.0.0 instance Ord1 [] where liftCompare _ [] [] = EQ liftCompare _ [] (_:_) = LT liftCompare _ (_:_) [] = GT liftCompare comp (x:xs) (y:ys) = comp x y `mappend` liftCompare comp xs ys -- | @since 4.9.0.0 instance Read1 [] where liftReadPrec _ rl = rl liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance Show1 [] where liftShowsPrec _ sl _ = sl -- | @since 4.10.0.0 instance Eq1 NonEmpty where liftEq eq (a :| as) (b :| bs) = eq a b && liftEq eq as bs -- | @since 4.10.0.0 instance Ord1 NonEmpty where liftCompare cmp (a :| as) (b :| bs) = cmp a b `mappend` liftCompare cmp as bs -- | @since 4.10.0.0 instance Read1 NonEmpty where liftReadsPrec rdP rdL p s = readParen (p > 5) (\s' -> do (a, s'') <- rdP 6 s' (":|", s''') <- lex s'' (as, s'''') <- rdL s''' return (a :| as, s'''')) s -- | @since 4.10.0.0 instance Show1 NonEmpty where liftShowsPrec shwP shwL p (a :| as) = showParen (p > 5) $ shwP 6 a . showString " :| " . shwL as -- | @since 4.9.0.0 instance Eq2 (,) where liftEq2 e1 e2 (x1, y1) (x2, y2) = e1 x1 x2 && e2 y1 y2 -- | @since 4.9.0.0 instance Ord2 (,) where liftCompare2 comp1 comp2 (x1, y1) (x2, y2) = comp1 x1 x2 `mappend` comp2 y1 y2 -- | @since 4.9.0.0 instance Read2 (,) where liftReadPrec2 rp1 _ rp2 _ = parens $ paren $ do x <- rp1 expectP (Punc ",") y <- rp2 return (x,y) liftReadListPrec2 = liftReadListPrec2Default liftReadList2 = liftReadList2Default -- | @since 4.9.0.0 instance Show2 (,) where liftShowsPrec2 sp1 _ sp2 _ _ (x, y) = showChar '(' . sp1 0 x . showChar ',' . sp2 0 y . showChar ')' -- | @since 4.9.0.0 instance (Eq a) => Eq1 ((,) a) where liftEq = liftEq2 (==) -- | @since 4.9.0.0 instance (Ord a) => Ord1 ((,) a) where liftCompare = liftCompare2 compare -- | @since 4.9.0.0 instance (Read a) => Read1 ((,) a) where liftReadPrec = liftReadPrec2 readPrec readListPrec liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance (Show a) => Show1 ((,) a) where liftShowsPrec = liftShowsPrec2 showsPrec showList -- | @since 4.9.0.0 instance Eq2 Either where liftEq2 e1 _ (Left x) (Left y) = e1 x y liftEq2 _ _ (Left _) (Right _) = False liftEq2 _ _ (Right _) (Left _) = False liftEq2 _ e2 (Right x) (Right y) = e2 x y -- | @since 4.9.0.0 instance Ord2 Either where liftCompare2 comp1 _ (Left x) (Left y) = comp1 x y liftCompare2 _ _ (Left _) (Right _) = LT liftCompare2 _ _ (Right _) (Left _) = GT liftCompare2 _ comp2 (Right x) (Right y) = comp2 x y -- | @since 4.9.0.0 instance Read2 Either where liftReadPrec2 rp1 _ rp2 _ = readData $ readUnaryWith rp1 "Left" Left <|> readUnaryWith rp2 "Right" Right liftReadListPrec2 = liftReadListPrec2Default liftReadList2 = liftReadList2Default -- | @since 4.9.0.0 instance Show2 Either where liftShowsPrec2 sp1 _ _ _ d (Left x) = showsUnaryWith sp1 "Left" d x liftShowsPrec2 _ _ sp2 _ d (Right x) = showsUnaryWith sp2 "Right" d x -- | @since 4.9.0.0 instance (Eq a) => Eq1 (Either a) where liftEq = liftEq2 (==) -- | @since 4.9.0.0 instance (Ord a) => Ord1 (Either a) where liftCompare = liftCompare2 compare -- | @since 4.9.0.0 instance (Read a) => Read1 (Either a) where liftReadPrec = liftReadPrec2 readPrec readListPrec liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance (Show a) => Show1 (Either a) where liftShowsPrec = liftShowsPrec2 showsPrec showList -- Instances for other functors defined in the base package -- | @since 4.9.0.0 instance Eq1 Identity where liftEq eq (Identity x) (Identity y) = eq x y -- | @since 4.9.0.0 instance Ord1 Identity where liftCompare comp (Identity x) (Identity y) = comp x y -- | @since 4.9.0.0 instance Read1 Identity where liftReadPrec rp _ = readData $ readUnaryWith rp "Identity" Identity liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance Show1 Identity where liftShowsPrec sp _ d (Identity x) = showsUnaryWith sp "Identity" d x -- | @since 4.9.0.0 instance Eq2 Const where liftEq2 eq _ (Const x) (Const y) = eq x y -- | @since 4.9.0.0 instance Ord2 Const where liftCompare2 comp _ (Const x) (Const y) = comp x y -- | @since 4.9.0.0 instance Read2 Const where liftReadPrec2 rp _ _ _ = readData $ readUnaryWith rp "Const" Const liftReadListPrec2 = liftReadListPrec2Default liftReadList2 = liftReadList2Default -- | @since 4.9.0.0 instance Show2 Const where liftShowsPrec2 sp _ _ _ d (Const x) = showsUnaryWith sp "Const" d x -- | @since 4.9.0.0 instance (Eq a) => Eq1 (Const a) where liftEq = liftEq2 (==) -- | @since 4.9.0.0 instance (Ord a) => Ord1 (Const a) where liftCompare = liftCompare2 compare -- | @since 4.9.0.0 instance (Read a) => Read1 (Const a) where liftReadPrec = liftReadPrec2 readPrec readListPrec liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- | @since 4.9.0.0 instance (Show a) => Show1 (Const a) where liftShowsPrec = liftShowsPrec2 showsPrec showList -- Proxy unfortunately imports this module, hence these instances are placed -- here, -- | @since 4.9.0.0 instance Eq1 Proxy where liftEq _ _ _ = True -- | @since 4.9.0.0 instance Ord1 Proxy where liftCompare _ _ _ = EQ -- | @since 4.9.0.0 instance Show1 Proxy where liftShowsPrec _ _ _ _ = showString "Proxy" -- | @since 4.9.0.0 instance Read1 Proxy where liftReadPrec _ _ = parens (expectP (Ident "Proxy") *> pure Proxy) liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault -- Building blocks -- | @'readsData' p d@ is a parser for datatypes where each alternative -- begins with a data constructor. It parses the constructor and -- passes it to @p@. Parsers for various constructors can be constructed -- with 'readsUnary', 'readsUnary1' and 'readsBinary1', and combined with -- @mappend@ from the @Monoid@ class. -- -- @since 4.9.0.0 readsData :: (String -> ReadS a) -> Int -> ReadS a readsData reader d = readParen (d > 10) $ \ r -> [res | (kw,s) <- lex r, res <- reader kw s] -- | @'readData' p@ is a parser for datatypes where each alternative -- begins with a data constructor. It parses the constructor and -- passes it to @p@. Parsers for various constructors can be constructed -- with 'readUnaryWith' and 'readBinaryWith', and combined with -- '(<|>)' from the 'Alternative' class. -- -- @since 4.10.0.0 readData :: ReadPrec a -> ReadPrec a readData reader = parens $ prec 10 reader -- | @'readsUnaryWith' rp n c n'@ matches the name of a unary data constructor -- and then parses its argument using @rp@. -- -- @since 4.9.0.0 readsUnaryWith :: (Int -> ReadS a) -> String -> (a -> t) -> String -> ReadS t readsUnaryWith rp name cons kw s = [(cons x,t) | kw == name, (x,t) <- rp 11 s] -- | @'readUnaryWith' rp n c'@ matches the name of a unary data constructor -- and then parses its argument using @rp@. -- -- @since 4.10.0.0 readUnaryWith :: ReadPrec a -> String -> (a -> t) -> ReadPrec t readUnaryWith rp name cons = do expectP $ Ident name x <- step rp return $ cons x -- | @'readsBinaryWith' rp1 rp2 n c n'@ matches the name of a binary -- data constructor and then parses its arguments using @rp1@ and @rp2@ -- respectively. -- -- @since 4.9.0.0 readsBinaryWith :: (Int -> ReadS a) -> (Int -> ReadS b) -> String -> (a -> b -> t) -> String -> ReadS t readsBinaryWith rp1 rp2 name cons kw s = [(cons x y,u) | kw == name, (x,t) <- rp1 11 s, (y,u) <- rp2 11 t] -- | @'readBinaryWith' rp1 rp2 n c'@ matches the name of a binary -- data constructor and then parses its arguments using @rp1@ and @rp2@ -- respectively. -- -- @since 4.10.0.0 readBinaryWith :: ReadPrec a -> ReadPrec b -> String -> (a -> b -> t) -> ReadPrec t readBinaryWith rp1 rp2 name cons = do expectP $ Ident name x <- step rp1 y <- step rp2 return $ cons x y -- | @'showsUnaryWith' sp n d x@ produces the string representation of a -- unary data constructor with name @n@ and argument @x@, in precedence -- context @d@. -- -- @since 4.9.0.0 showsUnaryWith :: (Int -> a -> ShowS) -> String -> Int -> a -> ShowS showsUnaryWith sp name d x = showParen (d > 10) $ showString name . showChar ' ' . sp 11 x -- | @'showsBinaryWith' sp1 sp2 n d x y@ produces the string -- representation of a binary data constructor with name @n@ and arguments -- @x@ and @y@, in precedence context @d@. -- -- @since 4.9.0.0 showsBinaryWith :: (Int -> a -> ShowS) -> (Int -> b -> ShowS) -> String -> Int -> a -> b -> ShowS showsBinaryWith sp1 sp2 name d x y = showParen (d > 10) $ showString name . showChar ' ' . sp1 11 x . showChar ' ' . sp2 11 y -- Obsolete building blocks -- | @'readsUnary' n c n'@ matches the name of a unary data constructor -- and then parses its argument using 'readsPrec'. -- -- @since 4.9.0.0 {-# DEPRECATED readsUnary "Use readsUnaryWith to define liftReadsPrec" #-} readsUnary :: (Read a) => String -> (a -> t) -> String -> ReadS t readsUnary name cons kw s = [(cons x,t) | kw == name, (x,t) <- readsPrec 11 s] -- | @'readsUnary1' n c n'@ matches the name of a unary data constructor -- and then parses its argument using 'readsPrec1'. -- -- @since 4.9.0.0 {-# DEPRECATED readsUnary1 "Use readsUnaryWith to define liftReadsPrec" #-} readsUnary1 :: (Read1 f, Read a) => String -> (f a -> t) -> String -> ReadS t readsUnary1 name cons kw s = [(cons x,t) | kw == name, (x,t) <- readsPrec1 11 s] -- | @'readsBinary1' n c n'@ matches the name of a binary data constructor -- and then parses its arguments using 'readsPrec1'. -- -- @since 4.9.0.0 {-# DEPRECATED readsBinary1 "Use readsBinaryWith to define liftReadsPrec" #-} readsBinary1 :: (Read1 f, Read1 g, Read a) => String -> (f a -> g a -> t) -> String -> ReadS t readsBinary1 name cons kw s = [(cons x y,u) | kw == name, (x,t) <- readsPrec1 11 s, (y,u) <- readsPrec1 11 t] -- | @'showsUnary' n d x@ produces the string representation of a unary data -- constructor with name @n@ and argument @x@, in precedence context @d@. -- -- @since 4.9.0.0 {-# DEPRECATED showsUnary "Use showsUnaryWith to define liftShowsPrec" #-} showsUnary :: (Show a) => String -> Int -> a -> ShowS showsUnary name d x = showParen (d > 10) $ showString name . showChar ' ' . showsPrec 11 x -- | @'showsUnary1' n d x@ produces the string representation of a unary data -- constructor with name @n@ and argument @x@, in precedence context @d@. -- -- @since 4.9.0.0 {-# DEPRECATED showsUnary1 "Use showsUnaryWith to define liftShowsPrec" #-} showsUnary1 :: (Show1 f, Show a) => String -> Int -> f a -> ShowS showsUnary1 name d x = showParen (d > 10) $ showString name . showChar ' ' . showsPrec1 11 x -- | @'showsBinary1' n d x y@ produces the string representation of a binary -- data constructor with name @n@ and arguments @x@ and @y@, in precedence -- context @d@. -- -- @since 4.9.0.0 {-# DEPRECATED showsBinary1 "Use showsBinaryWith to define liftShowsPrec" #-} showsBinary1 :: (Show1 f, Show1 g, Show a) => String -> Int -> f a -> g a -> ShowS showsBinary1 name d x y = showParen (d > 10) $ showString name . showChar ' ' . showsPrec1 11 x . showChar ' ' . showsPrec1 11 y {- $example These functions can be used to assemble 'Read' and 'Show' instances for new algebraic types. For example, given the definition > data T f a = Zero a | One (f a) | Two a (f a) a standard 'Read1' instance may be defined as > instance (Read1 f) => Read1 (T f) where > liftReadPrec rp rl = readData $ > readUnaryWith rp "Zero" Zero <|> > readUnaryWith (liftReadPrec rp rl) "One" One <|> > readBinaryWith rp (liftReadPrec rp rl) "Two" Two > liftReadListPrec = liftReadListPrecDefault and the corresponding 'Show1' instance as > instance (Show1 f) => Show1 (T f) where > liftShowsPrec sp _ d (Zero x) = > showsUnaryWith sp "Zero" d x > liftShowsPrec sp sl d (One x) = > showsUnaryWith (liftShowsPrec sp sl) "One" d x > liftShowsPrec sp sl d (Two x y) = > showsBinaryWith sp (liftShowsPrec sp sl) "Two" d x y -}