diff --git a/src/Generics/EMGM/Base.hs b/src/Generics/EMGM/Base.hs index 8ab3b28..6ca61e5 100644 --- a/src/Generics/EMGM/Base.hs +++ b/src/Generics/EMGM/Base.hs @@ -1,9 +1,3 @@ -{-# OPTIONS_GHC -Wall #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE OverlappingInstances #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Base @@ -25,6 +19,13 @@ -- apply) for every datatype. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE OverlappingInstances #-} + module Generics.EMGM.Base ( module Generics.EMGM.Representation, @@ -77,6 +78,7 @@ class Generic g where -- -- The class context represents the intersection set of supported type -- classes. + rconstant :: (Enum a, Eq a, Ord a, Read a, Show a) => g a -- | Case for the primitive type 'Int'. (Default implementation: @@ -85,48 +87,68 @@ class Generic g where -- | Case for the primitive type 'Integer'. (Default implementation: -- 'rconstant'.) + rinteger :: g Integer -- | Case for the primitive type 'Float'. (Default implementation: -- 'rconstant'.) + rfloat :: g Float -- | Case for the primitive type 'Double'. (Default implementation: -- 'rconstant'.) + rdouble :: g Double -- | Case for the primitive type 'Char'. (Default implementation: -- 'rconstant'.) + rchar :: g Char -- | Case for the structural representation type 'Unit'. It is used to -- represent a constructor with no arguments. (Default implementation: -- 'rconstant'.) + runit :: g Unit -- | Case for the structural representation type @:+:@ (sum). It -- is used to represent alternative choices between constructors. (No -- default implementation.) + rsum :: g a -> g b -> g (a :+: b) -- | Case for the structural representation type @:*:@ (product). -- It is used to represent multiple arguments to a constructor. (No -- default implementation.) + rprod :: g a -> g b -> g (a :*: b) - -- | Case for constructors. While not necessary for every generic function, - -- this method is required for 'Read' and 'Show'. It is used to hold the - -- meta-information about a constructor ('ConDescr'), e.g. name, arity, - -- fixity, etc. (Since most generic functions do not use 'rcon' and simply pass - -- the value through, the default implementation is @const id@.) + -- | Case for constructors. It is used to hold the meta-information about a + -- constructor, e.g. name, arity, fixity, etc. This is not needed for many + -- generic functions, so the default implementation is: + -- + -- @ + -- rcon = const id + -- @ + rcon :: ConDescr -> g a -> g a + -- | Case for labeled field. Contains the label string. This is not needed for + -- many generic functions, so the default implementation is: + -- + -- @ + -- rlabel = const id + -- @ + + rlabel :: LblDescr -> g a -> g a + -- | Case for datatypes. This method is used to define the structural -- representation of an arbitrary Haskell datatype. The first argument is the -- embedding-projection pair, necessary for establishing the isomorphism -- between datatype and representation. The second argument is the -- run-time representation using the methods of 'Generic'. (No default -- implementation.) + rtype :: EP b a -> g a -> g b rint = rconstant @@ -137,6 +159,7 @@ class Generic g where runit = rconstant rcon = const id + rlabel = const id infixr 5 `rsum` infixr 6 `rprod` @@ -160,6 +183,7 @@ class Generic2 g where rsum2 :: g a1 a2 -> g b1 b2 -> g (a1 :+: b1) (a2 :+: b2) rprod2 :: g a1 a2 -> g b1 b2 -> g (a1 :*: b1) (a2 :*: b2) rcon2 :: ConDescr -> g a1 a2 -> g a1 a2 + rlabel2 :: LblDescr -> g a1 a2 -> g a1 a2 -- | See 'rtype'. This case is the primary difference that separates -- 'Generic2' from 'Generic'. Since we have two generic type parameters, we @@ -175,6 +199,7 @@ class Generic2 g where runit2 = rconstant2 rcon2 = const id + rlabel2 = const id infixr 5 `rsum2` infixr 6 `rprod2` @@ -200,6 +225,7 @@ class Generic3 g where rsum3 :: g a1 a2 a3 -> g b1 b2 b3 -> g (a1 :+: b1) (a2 :+: b2) (a3 :+: b3) rprod3 :: g a1 a2 a3 -> g b1 b2 b3 -> g (a1 :*: b1) (a2 :*: b2) (a3 :*: b3) rcon3 :: ConDescr -> g a1 a2 a3 -> g a1 a2 a3 + rlabel3 :: LblDescr -> g a1 a2 a3 -> g a1 a2 a3 -- | See 'rtype'. This case is the primary difference that separates -- 'Generic3' from 'Generic'. Since we have three generic type parameters, we @@ -215,6 +241,7 @@ class Generic3 g where runit3 = rconstant3 rcon3 = const id + rlabel3 = const id infixr 5 `rsum3` infixr 6 `rprod3` diff --git a/src/Generics/EMGM/Data/Bool.hs b/src/Generics/EMGM/Data/Bool.hs index 58ee12b..473f985 100644 --- a/src/Generics/EMGM/Data/Bool.hs +++ b/src/Generics/EMGM/Data/Bool.hs @@ -1,11 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} -{-# OPTIONS -fno-warn-orphans #-} -{- OPTIONS -ddump-splices -} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Data.Bool @@ -19,6 +11,16 @@ -- Summary: Generic representation and instances for 'Bool'. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} +{-# OPTIONS -fno-warn-orphans #-} +{- OPTIONS -ddump-splices -} + module Generics.EMGM.Data.Bool ( epBool, conFalse, @@ -56,11 +58,11 @@ epBool = EP fromBool toBool -- | Constructor description for 'False'. conFalse :: ConDescr -conFalse = ConDescr "False" 0 [] Nonfix +conFalse = ConDescr "False" 0 False Prefix -- | Constructor description for 'True'. conTrue :: ConDescr -conTrue = ConDescr "True" 0 [] Nonfix +conTrue = ConDescr "True" 0 False Prefix -- | Representation of 'Bool' for 'rep'. repBool :: (Generic g) => g Bool diff --git a/src/Generics/EMGM/Data/Either.hs b/src/Generics/EMGM/Data/Either.hs index 61ee161..d97be31 100644 --- a/src/Generics/EMGM/Data/Either.hs +++ b/src/Generics/EMGM/Data/Either.hs @@ -1,11 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} -{-# OPTIONS -fno-warn-orphans #-} -{- OPTIONS -ddump-splices -} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Data.Either @@ -19,6 +11,16 @@ -- Summary: Generic representation and instances for 'Either'. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} +{-# OPTIONS -fno-warn-orphans #-} +{- OPTIONS -ddump-splices -} + module Generics.EMGM.Data.Either ( epEither, conLeft, @@ -56,11 +58,11 @@ epEither = EP fromEither toEither -- | Constructor description for 'Left'. conLeft :: ConDescr -conLeft = ConDescr "Left" 1 [] Nonfix +conLeft = ConDescr "Left" 1 False Prefix -- | Constructor description for 'Right'. conRight :: ConDescr -conRight = ConDescr "Right" 1 [] Nonfix +conRight = ConDescr "Right" 1 False Prefix -- | Representation of 'Either' for 'frep'. frepEither :: (Generic g) => g a -> g b -> g (Either a b) diff --git a/src/Generics/EMGM/Data/List.hs b/src/Generics/EMGM/Data/List.hs index 7b989d1..5692fab 100644 --- a/src/Generics/EMGM/Data/List.hs +++ b/src/Generics/EMGM/Data/List.hs @@ -1,10 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} -{-# OPTIONS -fno-warn-orphans #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Data.List @@ -18,6 +11,15 @@ -- Summary: Generic representation and instances for lists. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} +{-# OPTIONS -fno-warn-orphans #-} + module Generics.EMGM.Data.List ( epList, conNil, @@ -55,11 +57,11 @@ epList = EP fromList toList -- | Constructor description for ''nil'': @[]@. conNil :: ConDescr -conNil = ConDescr "[]" 0 [] Nonfix +conNil = ConDescr "[]" 0 False Prefix -- | Constructor description for ''cons'': @(:)@. conCons :: ConDescr -conCons = ConDescr ":" 2 [] (Infixr 5) +conCons = ConDescr ":" 2 False (Infix RightAssoc 5) -- | Representation of lists for 'frep'. frepList :: (Generic g) => g a -> g [a] diff --git a/src/Generics/EMGM/Data/Maybe.hs b/src/Generics/EMGM/Data/Maybe.hs index 0686346..56f7e9d 100644 --- a/src/Generics/EMGM/Data/Maybe.hs +++ b/src/Generics/EMGM/Data/Maybe.hs @@ -1,11 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} -{-# OPTIONS -fno-warn-orphans #-} -{- OPTIONS -ddump-splices -} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Data.Maybe @@ -19,6 +11,16 @@ -- Summary: Generic representation and instances for 'Maybe'. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} +{-# OPTIONS -fno-warn-orphans #-} +{- OPTIONS -ddump-splices -} + module Generics.EMGM.Data.Maybe ( epMaybe, conNothing, @@ -56,11 +58,11 @@ epMaybe = EP fromMaybe toMaybe -- | Constructor description for 'Nothing'. conNothing :: ConDescr -conNothing = ConDescr "Nothing" 0 [] Nonfix +conNothing = ConDescr "Nothing" 0 False Prefix -- | Constructor description for 'Just'. conJust :: ConDescr -conJust = ConDescr "Just" 1 [] Nonfix +conJust = ConDescr "Just" 1 False Prefix -- | Representation of 'Maybe' for 'frep'. frepMaybe :: (Generic g) => g a -> g (Maybe a) diff --git a/src/Generics/EMGM/Data/Tuple.hs b/src/Generics/EMGM/Data/Tuple.hs index 1ba8d04..5ce52dd 100644 --- a/src/Generics/EMGM/Data/Tuple.hs +++ b/src/Generics/EMGM/Data/Tuple.hs @@ -1,10 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} -{-# OPTIONS -fno-warn-orphans #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Data.Tuple @@ -19,6 +12,15 @@ -- (''unit'') and 2 to 7. ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} +{-# OPTIONS -fno-warn-orphans #-} + module Generics.EMGM.Data.Tuple ( -- * Unit: @()@ @@ -101,7 +103,7 @@ epTuple0 = EP (\() -> Unit) -- | Constructor description for @()@. conTuple0 :: ConDescr -conTuple0 = ConDescr "()" 0 [] Nonfix +conTuple0 = ConDescr "()" 0 False Prefix -- | Representation of @()@ for 'rep'. repTuple0 :: (Generic g) => g () @@ -145,7 +147,7 @@ epTuple2 = EP (\(a,b) -> a :*: b) -- | Constructor description for @(,)@. conTuple2 :: ConDescr -conTuple2 = ConDescr "(,)" 2 [] Nonfix +conTuple2 = ConDescr "(,)" 2 False Prefix -- | Representation of @(,)@ for 'frep'. frepTuple2 :: (Generic g) => g a -> g b -> g (a,b) @@ -189,7 +191,7 @@ epTuple3 = EP (\(a,b,c) -> a :*: b :*: c) -- | Constructor description for @(,,)@. conTuple3 :: ConDescr -conTuple3 = ConDescr "(,,)" 3 [] Nonfix +conTuple3 = ConDescr "(,,)" 3 False Prefix -- | Representation of @(,,)@ for 'frep'. frepTuple3 :: (Generic g) => g a -> g b -> g c -> g (a,b,c) @@ -235,7 +237,7 @@ epTuple4 = EP (\(a,b,c,d) -> a :*: b :*: c :*: d) -- | Constructor description for @(,,,)@. conTuple4 :: ConDescr -conTuple4 = ConDescr "(,,,)" 4 [] Nonfix +conTuple4 = ConDescr "(,,,)" 4 False Prefix -- | Representation of @(,,,)@ for 'frep'. frepTuple4 :: (Generic g) => g a -> g b -> g c -> g d -> g (a,b,c,d) @@ -281,7 +283,7 @@ epTuple5 = EP (\(a,b,c,d,e) -> a :*: b :*: c :*: d :*: e) -- | Constructor description for @(,,,,)@. conTuple5 :: ConDescr -conTuple5 = ConDescr "(,,,,)" 5 [] Nonfix +conTuple5 = ConDescr "(,,,,)" 5 False Prefix -- | Representation of @(,,,,)@ for 'frep'. frepTuple5 :: (Generic g) => g a -> g b -> g c -> g d -> g e -> g (a,b,c,d,e) @@ -327,7 +329,7 @@ epTuple6 = EP (\(a,b,c,d,e,f) -> a :*: b :*: c :*: d :*: e :*: f) -- | Constructor description for @(,,,,,)@. conTuple6 :: ConDescr -conTuple6 = ConDescr "(,,,,,)" 6 [] Nonfix +conTuple6 = ConDescr "(,,,,,)" 6 False Prefix -- | Representation of @(,,,,,)@ for 'frep'. frepTuple6 :: (Generic g) => g a -> g b -> g c -> g d -> g e -> g f -> g (a,b,c,d,e,f) @@ -374,7 +376,7 @@ epTuple7 = EP (\(a,b,c,d,e,f,h) -> a :*: b :*: c :*: d :*: e :*: f :*: h) -- | Constructor description for @(,,,,,,)@. conTuple7 :: ConDescr -conTuple7 = ConDescr "(,,,,,)" 7 [] Nonfix +conTuple7 = ConDescr "(,,,,,)" 7 False Prefix -- | Representation of @(,,,,,,)@ for 'frep'. frepTuple7 :: (Generic g) => g a -> g b -> g c -> g d -> g e -> g f -> g h -> g (a,b,c,d,e,f,h) diff --git a/src/Generics/EMGM/Functions/Read.hs b/src/Generics/EMGM/Functions/Read.hs index f443f90..8460ba6 100644 --- a/src/Generics/EMGM/Functions/Read.hs +++ b/src/Generics/EMGM/Functions/Read.hs @@ -1,10 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Functions.Read @@ -34,6 +27,15 @@ -- See also "Generics.EMGM.Functions.Show". ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} + module Generics.EMGM.Functions.Read ( Read(..), readPrec, @@ -44,13 +46,10 @@ module Generics.EMGM.Functions.Read ( ) where import Prelude hiding (Read, read, reads, readsPrec) -import qualified Prelude as P (Read) import Data.List (find) -import Control.Monad -import Debug.Trace import Text.ParserCombinators.ReadPrec (ReadPrec, step, (+++), pfail, lift, - look, readPrec_to_S, readPrec_to_P) + readPrec_to_S, readPrec_to_P) import qualified Text.ParserCombinators.ReadPrec as RP (prec) import Text.ParserCombinators.ReadP (ReadP) import Text.Read (Lexeme(Punc), lexP, parens, reset) @@ -67,21 +66,13 @@ import Generics.EMGM.Base -- | The type of a generic function that takes a constructor-type argument and -- returns a parser combinator for some type. + newtype Read a = Read { selRead :: ConType -> ReadPrec a } ----------------------------------------------------------------------------- -- Utility functions ----------------------------------------------------------------------------- --- | "Look and trace" - print the unconsumed part of the input string -ltrace :: String -> ReadPrec () -ltrace = - let debug = False - in if debug - then \s -> do la <- look - (trace $ "<<" ++ la ++ ">> " ++ s) $ return () - else const $ do return () - comma :: ReadPrec () comma = do Punc "," <- lexP return () @@ -127,173 +118,102 @@ tuple4 pa pb pc pd = -- | @(paren p)@ parses \"{P0}\" where @p@ parses \"P0\" at precedence 0 braces :: ReadPrec a -> ReadPrec a -braces p = do ltraceme "{ before" - Punc "{" <- lexP - ltraceme "{ after" +braces p = do Punc "{" <- lexP x <- reset p - ltraceme "} before" Punc "}" <- lexP - ltraceme "} after" return x - where ltraceme s = ltrace $ "braces: " ++ s -- | Parse a Haskell token and verify that it is the one expected. lexT :: String -> ReadPrec () lexT expected = do found <- lift hsLex if found == expected - then do ltraceme "success" - return () - else do ltraceme $ "fnd=" ++ found ++ " FAIL" - pfail - where ltraceme s = ltrace $ "lexT: exp=" ++ expected ++ " -> " ++ s - --- | Parse a record entry: "label = x[,]" where x comes from the parameter --- parser @p@. -recEntry :: Bool -> String -> ReadPrec a -> ReadPrec a -recEntry isComma label p = - do lexT label - ltraceme "before =" - equals - ltraceme "after =" - x <- p - ltraceme "after p" - if isComma - then do ltraceme "before ," - comma - return x - else do ltraceme "no ," - return x - where ltraceme s = - ltrace $ "recEntry: com=" ++ show isComma ++ - " lbl=" ++ label ++ " " ++ s + then return () + else pfail ----------------------------------------------------------------------------- -- Generic instance declaration ----------------------------------------------------------------------------- -rconstantRead :: (P.Read a) => ConType -> ReadPrec a -rconstantRead ct = - case ct of - - -- Standard constructor - ConStd -> - do ltraceme "ConStd" - TR.readPrec - - -- Record-style constructor with 1 label - ConRec (label:[]) -> - do ltraceme "ConRec1" - recEntry False label TR.readPrec - - -- No other patterns expected - _ -> - do ltraceme "FAIL" - pfail - - where ltraceme s = ltrace $ "rconstantRead: " ++ s - rsumRead :: Read a -> Read b -> ConType -> ReadPrec (a :+: b) rsumRead ra rb _ = - do ltrace "rsumRead:" - (return . L =<< selRead ra ConStd) +++ (return . R =<< selRead rb ConStd) + (fmap L $ selRead ra UnknownC) +++ (fmap R $ selRead rb UnknownC) rprodRead :: Read a -> Read b -> ConType -> ReadPrec (a :*: b) rprodRead ra rb ct = case ct of -- Standard nonfix constructor - ConStd -> - do ltraceme "ConStd (a)" - a <- step (selRead ra ConStd) - ltraceme "ConStd (b)" - b <- step (selRead rb ConStd) + NormalC -> + do a <- step (selRead ra NormalC) + b <- step (selRead rb NormalC) return (a :*: b) -- Standard infix constructor - ConIfx symbol -> - do ltraceme "ConIfx (a)" - a <- step (selRead ra ConStd) + InfixC symbol -> + do a <- step (selRead ra NormalC) lexT symbol - ltraceme "ConIfx (b)" - b <- step (selRead rb ConStd) + b <- step (selRead rb NormalC) return (a :*: b) -- Record-style constructor - ConRec (label:labels) -> - do ltraceme "ConRec2 (a)" - a <- step (recEntry True label (selRead ra ConStd)) - ltraceme "ConRec2 (b)" - b <- step $ selRead rb (ConRec (labels)) + RecordC -> + do a <- step $ selRead ra RecordC + comma + b <- step $ selRead rb RecordC return (a :*: b) -- No other patterns expected _ -> - do ltraceme "FAIL" - pfail - - where - ltraceme s = ltrace $ "rprodRead: " ++ show ct ++ " " ++ s + pfail rconRead :: ConDescr -> Read a -> ConType -> ReadPrec a rconRead cd ra _ = parens $ case cd of - -- Standard nonfix constructor - ConDescr name _ [] Nonfix -> - do ltraceme "ConStd" - lexT name - step $ selRead ra ConStd - - -- Standard infix constructor - ConDescr name _ [] fixity -> - do ltraceme "ConIfx" - let p = prec fixity - RP.prec p $ step $ selRead ra $ ConIfx name - - -- Record-style nonfix constructor - ConDescr name _ labels Nonfix -> - do ltraceme "ConRec (a)" - lexT name - braces $ step $ selRead ra $ ConRec labels - - -- Record-style infix constructor - ConDescr name _ labels _ -> - do ltraceme "ConRec (b)" - paren (lexT name) - braces $ step $ selRead ra $ ConRec labels - - where ltraceme s = ltrace $ "rconRead: " ++ show cd ++ " " ++ s + -- Normal prefix + ConDescr name _ False Prefix -> + do lexT name + step $ selRead ra NormalC + + -- Infix without record syntax + ConDescr name _ False fixity -> + do let p = prec fixity + RP.prec p $ step $ selRead ra $ InfixC name + + -- Record-style prefix + ConDescr name _ True Prefix -> + do lexT name + braces $ step $ selRead ra RecordC + + -- Record-style infix: We don't actually use the fixity info here. We just + -- need to wrap the symbol name in parens. + ConDescr name _ True _ -> + do paren (lexT name) + braces $ step $ selRead ra RecordC + +rlabelRead :: LblDescr -> Read a -> ConType -> ReadPrec a +rlabelRead (LblDescr label) ra _ = + do lexT label + equals + selRead ra UnknownC rtypeRead :: EP d a -> Read a -> ConType -> ReadPrec d -rtypeRead ep ra ct = - case ct of - - -- Standard constructor - ConStd -> - do ltraceme "ConStd" - fmap (to ep) $ selRead ra ConStd - - -- Record-style constructor - ConRec (label:[]) -> - do ltraceme "ConRec" - fmap (to ep) $ recEntry False label (selRead ra ConStd) - - -- No other patterns expected - _ -> - do ltraceme "FAIL" - pfail - - where - ltraceme s = ltrace $ "rtypeRead: " ++ show ct ++ " " ++ s +rtypeRead ep ra = fmap (to ep) . selRead ra instance Generic Read where - rconstant = Read rconstantRead - rsum ra rb = Read (rsumRead ra rb) - rprod ra rb = Read (rprodRead ra rb) - rcon cd ra = Read (rconRead cd ra) - rtype ep ra = Read (rtypeRead ep ra) + rint = Read $ const TR.readPrec + rinteger = Read $ const TR.readPrec + rfloat = Read $ const TR.readPrec + rdouble = Read $ const TR.readPrec + rchar = Read $ const TR.readPrec + runit = Read $ const $ return Unit + rsum ra rb = Read $ rsumRead ra rb + rprod ra rb = Read $ rprodRead ra rb + rcon cd ra = Read $ rconRead cd ra + rlabel ld ra = Read $ rlabelRead ld ra + rtype ep ra = Read $ rtypeRead ep ra ----------------------------------------------------------------------------- -- Rep instance declarations @@ -366,7 +286,7 @@ instance (Rep Read a, Rep Read b, Rep Read c, Rep Read d, Rep Read e, -- "Text.ParserCombinators.ReadPrec" and should be similar to a derived -- implementation of 'Text.Read.readPrec'. readPrec :: (Rep Read a) => ReadPrec a -readPrec = selRead rep ConStd +readPrec = selRead rep UnknownC -- | Attempt to parse a value from the front of the string using the given -- precedence. 'readsPrec' returns a list of (parsed value, remaining string) diff --git a/src/Generics/EMGM/Functions/Show.hs b/src/Generics/EMGM/Functions/Show.hs index f248842..8fcb619 100644 --- a/src/Generics/EMGM/Functions/Show.hs +++ b/src/Generics/EMGM/Functions/Show.hs @@ -1,10 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverlappingInstances #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Functions.Show @@ -33,6 +26,15 @@ -- See also "Generics.EMGM.Functions.Read". ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverlappingInstances #-} + module Generics.EMGM.Functions.Show ( Show(..), showsPrec, @@ -55,15 +57,15 @@ type ShowsPrec a = Int -> a -> ShowS -- | The type of a generic function that takes a constructor-type argument, a -- number (precedence), and a value and returns a 'ShowS' function. + newtype Show a = Show { selShow :: ConType -> Int -> a -> ShowS } --- NOTE: Use full type here instead of 'ShowsPrec' for Haddock. ----------------------------------------------------------------------------- -- Utility functions ----------------------------------------------------------------------------- -showSpace :: ShowS -showSpace = showChar ' ' +showSpace :: Bool -> ShowS +showSpace c = if c then showChar ' ' else id showBraces :: ShowsPrec a -> ShowsPrec a showBraces showsPrec' p x = @@ -75,58 +77,38 @@ showTuple :: [ShowS] -> ShowS showTuple ss = showParen True $ foldr1 (\s r -> s . showChar ',' . r) ss -recEntry :: Bool -> String -> ShowsPrec a -> ShowsPrec a -recEntry comma label showsPrec' _ x = - showString label . - showString " = " . - showsPrec' minPrec x . -- Reset precedence for record fields - showString (if comma then ", " else "") - ----------------------------------------------------------------------------- -- Generic instance declaration ----------------------------------------------------------------------------- -rconstantShow :: (P.Show a) => ConType -> ShowsPrec a -rconstantShow ct = - case ct of - - -- Standard constructor - ConStd -> P.showsPrec - - -- Record-style constructor with 1 label - ConRec (label:[]) -> recEntry False label P.showsPrec - - -- No other patterns expected - other -> - error $ "rconstantShow: Unexpected constructor: '" ++ P.show other ++ "'" - rsumShow :: Show a -> Show b -> ConType -> ShowsPrec (a :+: b) -rsumShow ra _ _ p (L a) = selShow ra ConStd p a -rsumShow _ rb _ p (R b) = selShow rb ConStd p b +rsumShow ra _ _ p (L a) = selShow ra UnknownC p a +rsumShow _ rb _ p (R b) = selShow rb UnknownC p b rprodShow :: Show a -> Show b -> ConType -> ShowsPrec (a :*: b) rprodShow ra rb ct p (a :*: b) = case ct of - -- Standard nonfix constructor - ConStd -> - selShowStep ra ConStd p a . - showSpace . - selShowStep rb ConStd p b + -- Normal prefix + NormalC -> + selShowStep ra NormalC p a . + showSpace True . + selShowStep rb NormalC p b - -- Standard infix constructor - ConIfx symbol -> - selShowStep ra ConStd p a . - showSpace . + -- Infix without record syntax + InfixC symbol -> + selShowStep ra NormalC p a . + showSpace True . showString symbol . - showSpace . - selShowStep rb ConStd p b + showSpace True . + selShowStep rb NormalC p b - -- Record-style constructor - ConRec (label:labels) -> + -- Record-style + RecordC -> let p' = p + 1 in - recEntry True label (selShowStep ra ConStd) p' a . - selShowStep rb (ConRec (labels)) p' b + selShowStep ra RecordC p' a . + showString ", " . + selShowStep rb RecordC p' b -- No other patterns expected other -> @@ -138,64 +120,65 @@ rconShow :: ConDescr -> Show a -> ConType -> ShowsPrec a rconShow cd ra _ p a = case cd of - -- Standard nonfix constructor - ConDescr name arity [] Nonfix -> + -- Normal prefix + ConDescr name arity False Prefix -> let hasArgs = arity > 0 in -- Don't show parens if constructor has no arguments showParen (p > appPrec && hasArgs) $ showString name . - showString (if hasArgs then " " else "") . - showConStep ConStd appPrec a + showSpace hasArgs . + step NormalC appPrec a - -- Standard infix constructor - ConDescr name _ [] fixity -> + -- Infix without record syntax + ConDescr name _ False fixity -> let conPrec = prec fixity in showParen (p > conPrec) $ - showConStep (ConIfx name) conPrec a - - -- Record-style nonfix constructor - ConDescr name _ labels Nonfix -> - -- NOTE: Technically, we can use 'recPrec' below, because the precedence - -- for record construction is higher than function application. However, - -- since GHC puts parens for 'appRec', we'll put them. That way, we can - -- compare string output to deriving Show for testing. - showParen (p > appPrec) $ - showString name . - showSpace . - showBraces (selShow ra (ConRec labels)) minPrec a + step (InfixC name) conPrec a - -- Record-style infix constructor - ConDescr name _ labels _ -> - showParen True (showString name) . - showSpace . - showBraces (showConStep (ConRec labels)) p a + -- Record-style prefix + ConDescr name _ True Prefix -> - where showConStep ct = selShow ra ct . (+1) + -- NOTE: Technically, we can use 'recPrec' instead of 'appRec' here. The + -- precedence for record construction is higher than function application. + -- However, since GHC puts parens for application, we'll put them, too. + -- That way, we can test the output with a derived Show instance. -rtypeShow :: EP b a -> Show a -> ConType -> ShowsPrec b -rtypeShow ep ra ct = - case ct of + showParen (p > appPrec) $ + showString name . + showSpace True . + showBraces (selShow ra RecordC) minPrec a - -- Standard constructor - ConStd -> - selShowFrom ConStd + -- Record-style infix: We don't actually use the fixity info here. We just + -- need to wrap the symbol name in parens. + ConDescr name _ True _ -> + showParen True (showString name) . + showSpace True . + showBraces (step RecordC) p a - -- Record-style constructor - ConRec (label:[]) -> - recEntry False label (selShowFrom ConStd) + where + step ct = selShow ra ct . (+1) - -- No other patterns expected - other -> - error $ "rtypeShow: Unexpected constructor: '" ++ P.show other ++ "'" +rlabelShow :: LblDescr -> Show a -> ConType -> ShowsPrec a +rlabelShow (LblDescr label) ra _ _ a = + showString label . + showString " = " . + selShow ra UnknownC minPrec a -- Reset precedence in the field - where selShowFrom ct' p = selShow ra ct' p . from ep +rtypeShow :: EP b a -> Show a -> ConType -> ShowsPrec b +rtypeShow ep ra ct p = selShow ra ct p . from ep instance Generic Show where - rconstant = Show rconstantShow - rsum ra rb = Show (rsumShow ra rb) - rprod ra rb = Show (rprodShow ra rb) - rcon cd ra = Show (rconShow cd ra) - rtype ep ra = Show (rtypeShow ep ra) + rint = Show $ const P.showsPrec + rinteger = Show $ const P.showsPrec + rfloat = Show $ const P.showsPrec + rdouble = Show $ const P.showsPrec + rchar = Show $ const P.showsPrec + runit = Show $ \_ _ _ -> id + rsum ra rb = Show $ rsumShow ra rb + rprod ra rb = Show $ rprodShow ra rb + rcon cd ra = Show $ rconShow cd ra + rlabel ld ra = Show $ rlabelShow ld ra + rtype ep ra = Show $ rtypeShow ep ra ----------------------------------------------------------------------------- -- Rep instance declarations @@ -203,7 +186,7 @@ instance Generic Show where -- | Ad-hoc instance for lists instance (Rep Show a) => Rep Show [a] where - rep = Show $ const $ const $ GHC.showList__ $ selShow rep ConStd minPrec + rep = Show $ const $ const $ GHC.showList__ $ selShow rep UnknownC minPrec -- | Ad-hoc instance for strings instance Rep Show String where @@ -271,7 +254,7 @@ showsPrec :: => Int -- ^ Operator precedence of the enclosing context (a number from 0 to 11). -> a -- ^ The value to be converted to a 'String'. -> ShowS -showsPrec = selShow rep ConStd +showsPrec = selShow rep UnknownC -- | A variant of 'showsPrec' with the minimum precedence (0). shows :: (Rep Show a) => a -> ShowS diff --git a/src/Generics/EMGM/Representation.hs b/src/Generics/EMGM/Representation.hs index 01fc1f4..eed8e12 100644 --- a/src/Generics/EMGM/Representation.hs +++ b/src/Generics/EMGM/Representation.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE TypeOperators #-} - ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Representation @@ -29,6 +27,10 @@ -- ----------------------------------------------------------------------------- +{-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} + module Generics.EMGM.Representation ( -- * Structure Representation @@ -40,13 +42,6 @@ module Generics.EMGM.Representation ( (:+:)(..), (:*:)(..), - -- * Embedding-Projection Pair - -- - -- | A pair of a function and its inverse form the isomorphism between a - -- datatype and its structure representation. - - EP(..), - -- * Constructor Description -- -- | A description of the syntax of each constructor provides useful auxiliary @@ -54,12 +49,21 @@ module Generics.EMGM.Representation ( ConDescr(..), ConType(..), + LblDescr(..), + + -- * Embedding-Projection Pair + -- + -- | A pair of a function and its inverse form the isomorphism between a + -- datatype and its structure representation. + + EP(..), -- * Fixity and Precedence -- | These are used to determine whether a constructor is infix or not and, if -- it is infix, what its associativity and precedence are. Fixity(..), + Associativity(..), Prec, prec, minPrec, @@ -74,8 +78,9 @@ import Text.ParserCombinators.ReadPrec (minPrec, Prec) infixr 5 :+: infixr 6 :*: --- | The \"unit\" encodes a constructor with no arguments. An analogous standard --- Haskell type is @()@. +-- | Encodes a constructor with no arguments. An analogous standard Haskell type +-- is @()@. + data Unit = Unit -- ^ The only value of type @Unit@ (ignoring @_|_@). deriving (Enum, Eq, Ord) @@ -106,6 +111,12 @@ data a :*: b = a :*: b -- ^ A pair of arguments deriving (Eq, Ord, Read, Show) +-- | Encodes the string label for a field in a constructor defined with labeled +-- fields (a.k.a. record syntax). + +newtype LblDescr = LblDescr String + deriving (Eq, Ord, Read, Show) + -- | The embedding-projection pair contains two functions for converting between -- the datatype and its representation. An @EP@ value preserves an isomorphism -- (ignoring @_|_@s) between a datatype and its structure representation. @@ -115,60 +126,68 @@ data EP d r , to :: (r -> d) -- ^ Project @d@atatype from its @r@epresentation. } --- | A constructor description containing useful meta-information about the --- syntax used in the data declaration. This is particularly useful in 'Read' --- and 'Show' but may also be helpful in other generic functions. +-- | Contains useful meta-information about the syntax used in a constructor +-- declaration. -- -- NOTE: It is important that the 'ConDescr' value accurately describe the -- syntax in a constructor declaration. An incorrect description may lead to -- faulty 'Read' or 'Show' operation. + data ConDescr = ConDescr - { conName :: String -- ^ Name of the constructor. If it is infix, - -- don't provide parentheses. + { -- | Name of the constructor (without parenthesese if infix). + conName :: String, - , conArity :: Int -- ^ Arity or number of arguments. + -- | Number of fields. + conArity :: Int, - , conLabels :: [String] -- ^ A list of labels used in record syntax. - -- They must be declared in the same order as - -- the @data@ declaration. The list should be - -- empty if the constructor is not a record. + -- | Uses labeled fields (a.k.a. record syntax). + conRecord :: Bool, - , conFixity :: Fixity -- ^ Infix or not, associativity, precedence. + -- | Fixity, associativity, precedence. + conFixity :: Fixity } deriving (Eq, Show) --- | The constructor type used in 'Read' and 'Show' to determine how to parse or --- print the constructor. +-- | Type of constructor syntax. Used in the generic functions 'Read' and +-- 'Show'. + data ConType - = ConStd -- ^ Standard (function-type, nonfix) - | ConRec [String] -- ^ Record-style (nonfix or infix) - | ConIfx String -- ^ Infix (no record syntax) + = UnknownC -- ^ Have not seen the rcon yet + | NormalC -- ^ Normal prefix-style constructor + | InfixC String -- ^ Infix with symbol (no record syntax) + | RecordC -- ^ Record-style (any fixity) deriving (Eq, Show) --- TODO: Need smart constructor(s) for ConDescr, so we can verify things. - --- | An identifier's fixity, associativity, and precedence. If not infix --- ('Nonfix'), the associativity and precedence of the identifier is the same as --- function application. If infix, the associativity is indicated by the --- constructor and the precedence is an argument to it. +-- | A constructor's fixity, associativity, and precedence. data Fixity - = Nonfix -- ^ Not infix. Associativity and precedence are the same as function application. - | Infix Prec -- ^ Non-associative infix with precedence. - | Infixl Prec -- ^ Left-associative infix with precedence. - | Infixr Prec -- ^ Right-associative Infix with precedence. - deriving (Eq, Show) + -- | Associativity and precedence are the same as function application. + = Prefix + | Infix Associativity Prec + deriving (Eq, Ord, Read, Show) + +-- | A constructor's associativity. +data Associativity + -- | Declared with infixl + = LeftAssoc + + -- | Declared with infixr + | RightAssoc + + -- | Declared with infix + | NotAssoc + deriving (Eq, Ord, Read, Show) + +-- TODO: Need smart constructor(s) for ConDescr, so we can verify things. -- | Get the precedence of a fixity value. prec :: Fixity -> Prec -prec Nonfix = appPrec -prec (Infix n) = n -prec (Infixl n) = n -prec (Infixr n) = n +prec Prefix = appPrec +prec (Infix _ n) = n -- | Maximum precedence: 11 maxPrec :: Prec -maxPrec = 11 +maxPrec = recPrec -- | Precedence for function application: 10 appPrec :: Prec diff --git a/tests/Compare.hs b/tests/Compare.hs index c4a2c2e..f620a75 100644 --- a/tests/Compare.hs +++ b/tests/Compare.hs @@ -56,7 +56,7 @@ test_min = test_f min P.min test_max :: (P.Show a, Data a, Ord a, Rep Compare a) => a -> a -> Test test_max = test_f max P.max -t1, t2 :: TTree (TTree Float) +t1, t2 :: T (T Float) t1 = L1 (L3 8.8 :^: 9.9) :<>: L4 (L4 (L2 (L3 11.11) (L1 (L1 22.22))) (L3 33.33)) (L5 0.44 (L3 55.55) 0.66) t2 = L1 (L3 8.8 :^: 9.9) :<>: L4 (L4 (L2 (L3 11.11) (L1 (L3 22.22))) (L3 33.33)) (L5 0.44 (L3 55.55) 0.66) diff --git a/tests/Everywhere.hs b/tests/Everywhere.hs index 92ee69f..1adb705 100644 --- a/tests/Everywhere.hs +++ b/tests/Everywhere.hs @@ -60,7 +60,7 @@ f_list_char2 [] = [] f_unit :: () -> () f_unit = id -f_ttree1 :: TTree Int -> TTree Int +f_ttree1 :: T Int -> T Int f_ttree1 (L1 4) = L1 7 f_ttree1 (L2 5 (L1 4)) = L1 9 f_ttree1 x = x @@ -94,8 +94,8 @@ tests = , test_e "(,,,,)" f_unit ((),(),(),(),()) id , test_e "(,,,,,)" f_unit ((),(),(),(),(),()) id , test_e "(,,,,,,)" f_unit ((),(),(),(),(),(),()) id - , test_e "TTree1" f_ttree1 (L1 4) f_ttree1 - , test_e "TTree2" f_ttree1 (L2 (5::Int) (L1 4)) (const (L2 5 (L1 7))) + , test_e "T1" f_ttree1 (L1 4) f_ttree1 + , test_e "T2" f_ttree1 (L2 (5::Int) (L1 4)) (const (L2 5 (L1 7))) ] , "Everywhere'" ~: @@ -120,8 +120,8 @@ tests = , test_e' "(,,,,)" f_unit ((),(),(),(),()) id , test_e' "(,,,,,)" f_unit ((),(),(),(),(),()) id , test_e' "(,,,,,,)" f_unit ((),(),(),(),(),(),()) id - , test_e' "TTree1" f_ttree1 (L1 4) f_ttree1 - , test_e' "TTree2" f_ttree1 (L2 (5::Int) (L1 4)) (const (L1 9)) + , test_e' "T1" f_ttree1 (L1 4) f_ttree1 + , test_e' "T2" f_ttree1 (L2 (5::Int) (L1 4)) (const (L1 9)) ] ] diff --git a/tests/ReadShow.hs b/tests/ReadShow.hs index 4b91e9b..ba72ce5 100644 --- a/tests/ReadShow.hs +++ b/tests/ReadShow.hs @@ -59,17 +59,17 @@ tests = , test_all True (Right '2' :: Either Float Char) , test_all True (Nothing :: Maybe Double) , test_all True (Just 256 :: Maybe Int) - , test_all True (L1 5 :: TTree Int) - , test_all True (L1 (Just 5) :: TTree (Maybe Int)) - , test_all True (L2 88 (L1 99) :: TTree Int) - , test_all True (L3 654 :: TTree Int) - , test_all True (Just (L3 654) :: Maybe (TTree Int)) - , test_all True (L4 (L2 1 (L3 2)) 3 :: TTree Int) - , test_all True (L5 101 (L4 (L3 102) 103) 104 :: TTree Int) - , test_all True (L3 'g' :^: 'a' :: TTree Char) - , test_all True ((L3 'F' :^: 'a') :^: 'g' :: TTree Char) - , test_all False (L1 1.1 :<>: L1 1.2 :^: 1.3 :: TTree Float) - , test_all False (L1 (L3 8.8 :^: 9.9) :<>: L4 (L4 (L2 (L3 11.11) (L1 (L1 22.22))) (L3 33.33)) (L5 0.44 (L3 55.55) 0.66) :: TTree (TTree Float)) + , test_all True (L1 5 :: T Int) + , test_all True (L1 (Just 5) :: T (Maybe Int)) + , test_all True (L2 88 (L1 99) :: T Int) + , test_all True (L3 654 :: T Int) + , test_all True (Just (L3 654) :: Maybe (T Int)) + , test_all True (L4 (L2 1 (L3 2)) 3 :: T Int) + , test_all True (L5 'a' (L4 (L3 102) 103) 104 :: T Int) + , test_all True (L3 8.0 :^: 8.0 :: T Char) + , test_all True ((L3 (-0.2) :^: 0.2) :^: 2.0 :: T Char) + , test_all False (L1 1.1 :<>: L1 1.2 :^: 1.3 :: T Float) + , test_all False (L1 (L3 8.8 :^: 9.9) :<>: L4 (L4 (L2 101 (L1 (L1 22.22))) (-1)) 55 :: T (T Float)) , test_all True [1,2,3,4,5 :: Int] , test_all True [[5.3,3.5],[35.0],[0.53 :: Float]] , test_all True "abcdefgh" diff --git a/tests/TTree.hs b/tests/TTree.hs index daea4c0..1b67be5 100644 --- a/tests/TTree.hs +++ b/tests/TTree.hs @@ -1,12 +1,3 @@ -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE DeriveDataTypeable #-} -{-# LANGUAGE OverlappingInstances #-} -{-# LANGUAGE UndecidableInstances #-} -{- OPTIONS -ddump-splices -} - ----------------------------------------------------------------------------- -- | -- Module : TTree @@ -16,27 +7,152 @@ -- Maintainer : generics@haskell.org ----------------------------------------------------------------------------- +-- {-# OPTIONS_GHC -Wall #-} + +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE OverlappingInstances #-} +{-# LANGUAGE UndecidableInstances #-} + module TTree where import Prelude hiding (Read, Show) import qualified Prelude as P (Read, Show) import Data.Generics (Data, Typeable) -import Generics.EMGM.Derive +import Generics.EMGM.Base +import Generics.EMGM.Functions.Collect +import Generics.EMGM.Functions.Everywhere infixr 6 :^: infixl 5 :<>: -data TTree a +data T a = L1 a - | L2 a (TTree a) - | L3 { unL3 :: a } - | L4 { unL4t :: TTree a, unL4a :: a } - | L5 { unL5a1 :: a, unL5t :: TTree a, unL5a2 :: a } - | TTree a :^: a - | (:<>:) { left :: TTree a, right :: TTree a } + | L2 Integer (T a) + | L3 { unL3 :: Double } + | L4 { unL4a :: T a, unL4b :: Int } + | L5 { unL5a :: Char, unL5b :: T a, unL5c :: a } + | T a :^: Float + | (:<>:) { unL7a :: T a, unL7b :: T a } deriving (P.Show, P.Read, Eq, Ord, Data, Typeable) -$(deriveWith [(":<>:", DefinedAs "L6")] ''TTree) -conL6 = ConDescr ":<>:" 2 ["left","right"] (Infixr 5) +type S a + {- L1 -} = a + {- L2 -} :+: Integer :*: T a + {- L3 -} :+: Double + {- L4 -} :+: T a :*: Int + {- L5 -} :+: Char :*: T a :*: a + {- :^: -} :+: T a :*: Float + {- :<>: -} :+: T a :*: T a + +fromT :: T a -> S a +fromT t = case t of + L1 x1 -> L x1 + L2 x1 x2 -> R (L (x1 :*: x2)) + L3 x1 -> R (R (L x1)) + L4 x1 x2 -> R (R (R (L (x1 :*: x2)))) + L5 x1 x2 x3 -> R (R (R (R (L (x1 :*: x2 :*: x3))))) + x1 :^: x2 -> R (R (R (R (R (L (x1 :*: x2)))))) + x1 :<>: x2 -> R (R (R (R (R (R (x1 :*: x2)))))) + +toT :: S a -> T a +toT s = case s of + L x1 -> L1 x1 + R (L (x1 :*: x2)) -> L2 x1 x2 + R (R (L x1)) -> L3 x1 + R (R (R (L (x1 :*: x2)))) -> L4 x1 x2 + R (R (R (R (L (x1 :*: x2 :*: x3))))) -> L5 x1 x2 x3 + R (R (R (R (R (L (x1 :*: x2)))))) -> x1 :^: x2 + R (R (R (R (R (R (x1 :*: x2)))))) -> x1 :<>: x2 + +epT :: EP (T a) (S a) +epT = EP fromT toT + +conL1 = ConDescr "L1" 1 False Prefix +conL2 = ConDescr "L2" 2 False Prefix +conL3 = ConDescr "L3" 1 True Prefix +conL4 = ConDescr "L4" 2 True Prefix +conL5 = ConDescr "L5" 3 True Prefix +conL6 = ConDescr ":^:" 2 False (Infix RightAssoc 6) +conL7 = ConDescr ":<>:" 2 True (Infix LeftAssoc 5) + +lblUnL3 = LblDescr "unL3" +lblUnL4a = LblDescr "unL4a" +lblUnL4b = LblDescr "unL4b" +lblUnL5a = LblDescr "unL5a" +lblUnL5b = LblDescr "unL5b" +lblUnL5c = LblDescr "unL5c" +lblUnL7a = LblDescr "unL7a" +lblUnL7b = LblDescr "unL7b" + +instance (Generic g, Rep g a, Rep g Char, Rep g Double, Rep g Float, Rep g Integer, Rep g Int) => Rep g (T a) where + rep = rtype epT + $ rcon conL1 rep + `rsum` rcon conL2 (rep `rprod` rep) + `rsum` rcon conL3 (rlabel lblUnL3 rep) + `rsum` rcon conL4 (rlabel lblUnL4a rep `rprod` rlabel lblUnL4b rep) + `rsum` rcon conL5 (rlabel lblUnL5a rep `rprod` rlabel lblUnL5b rep `rprod` rlabel lblUnL5c rep) + `rsum` rcon conL6 (rep `rprod` rep) + `rsum` rcon conL7 (rlabel lblUnL7a rep `rprod` rlabel lblUnL7b rep) + +instance (Generic g) => FRep g T where + frep ra = rtype epT + $ rcon conL1 ra + `rsum` rcon conL2 (rinteger `rprod` frep ra) + `rsum` rcon conL3 (rlabel lblUnL3 rdouble) + `rsum` rcon conL4 (rlabel lblUnL4a (frep ra) `rprod` rlabel lblUnL4b rint) + `rsum` rcon conL5 (rlabel lblUnL5a rchar `rprod` rlabel lblUnL5b (frep ra) `rprod` rlabel lblUnL5c ra) + `rsum` rcon conL6 (frep ra `rprod` rfloat) + `rsum` rcon conL7 (rlabel lblUnL7a (frep ra) `rprod` rlabel lblUnL7b (frep ra)) + +instance (Generic2 g) => FRep2 g T where + frep2 ra = rtype2 epT epT + $ rcon2 conL1 ra + `rsum2` rcon2 conL2 (rinteger2 `rprod2` frep2 ra) + `rsum2` rcon2 conL3 (rlabel2 lblUnL3 rdouble2) + `rsum2` rcon2 conL4 (rlabel2 lblUnL4a (frep2 ra) `rprod2` rlabel2 lblUnL4b rint2) + `rsum2` rcon2 conL5 (rlabel2 lblUnL5a rchar2 `rprod2` rlabel2 lblUnL5b (frep2 ra) `rprod2` rlabel2 lblUnL5c ra) + `rsum2` rcon2 conL6 (frep2 ra `rprod2` rfloat2) + `rsum2` rcon2 conL7 (rlabel2 lblUnL7a (frep2 ra) `rprod2` rlabel2 lblUnL7b (frep2 ra)) + +instance (Generic3 g) => FRep3 g T where + frep3 ra = rtype3 epT epT epT + $ rcon3 conL1 ra + `rsum3` rcon3 conL2 (rinteger3 `rprod3` frep3 ra) + `rsum3` rcon3 conL3 (rlabel3 lblUnL3 rdouble3) + `rsum3` rcon3 conL4 (rlabel3 lblUnL4a (frep3 ra) `rprod3` rlabel3 lblUnL4b rint3) + `rsum3` rcon3 conL5 (rlabel3 lblUnL5a rchar3 `rprod3` rlabel3 lblUnL5b (frep3 ra) `rprod3` rlabel3 lblUnL5c ra) + `rsum3` rcon3 conL6 (frep3 ra `rprod3` rfloat3) + `rsum3` rcon3 conL7 (rlabel3 lblUnL7a (frep3 ra) `rprod3` rlabel3 lblUnL7b (frep3 ra)) + +instance Rep (Collect (T a)) (T a) where + rep = Collect (:[]) + +instance (Rep (Everywhere (T a)) a) => Rep (Everywhere (T a)) (T a) where + rep = Everywhere app + where + app f x = + case x of + L1 x1 -> f (L1 (selEverywhere rep f x1)) + L2 x1 x2 -> f (L2 (selEverywhere rep f x1) (selEverywhere rep f x2)) + L3 x1 -> f (L3 (selEverywhere rep f x1)) + L4 x1 x2 -> f (L4 (selEverywhere rep f x1) (selEverywhere rep f x2)) + L5 x1 x2 x3 -> f (L5 (selEverywhere rep f x1) (selEverywhere rep f x2) (selEverywhere rep f x3)) + x1 :^: x2 -> f (selEverywhere rep f x1 :^: selEverywhere rep f x2) + x1 :<>: x2 -> f (selEverywhere rep f x1 :<>: selEverywhere rep f x2) + +instance Rep (Everywhere' (T a)) (T a) where + rep = Everywhere' ($) + +v1 = L1 (5 :: Int) +v2 = L2 37 v1 +v3 = L3 9999.9999 :: T Float +v4 = L4 v3 79 +v5 = L5 'a' v4 5.0 +v6 = v5 :^: 0.12345 +v7 = v6 :<>: v6