h&WfU      !"#$%&'()*+,-./0123456789:;<=>?@A Safe-Inferred"1<UG$sayableConstrM is a monadic context for describing the constraint parameters needed by 1 when generating sub-element Sayable constraints.sayableThis is the default annotation type for the Saying module. The Prettyprinter reannotate operation can be used to change this annotation into any other annotation type the client desires.The SayableAnn is an instance of IsLabel, so if OverloadedLabels is enabled, this can easily be specified: import qualified Prettyprinter as PP import Text.Sayable putStrLn $ sez @"info" $ PP.annotate #myann $ Hello &- "world!"  Doc ann) function (the first argument) to the Sayable in the second argument. This is different from the  # operator in that the former uses  to join two independent  ? values, whereas this operator applies a transformation (e.g. Prettyprinter.annotate AnnValue or )Prettyprinter.align . Prettyprinter.group ) to the  in the second  argument. sez @"info" $ PP.group &! t'"hi""hi" sayableA helper operator allowing a Sayable item to be composed with a Foldable series of Sayable items. This can be used when the second argument is a List, Sequence, Set, etc. to add all elements of the set (comma-separated).Note: this instance makes it easy to output lists, Sequence, NonEmpty.List, etc., but it can have undesireable effects for data structures whose Foldable (Functor) is irregular... for example, folding over a tuple only returns the B value of a tuple. Consider wrapping tuples in a newtype with an explicit Sayable to avoid this.*sez @"info" $ t'"three:" &* [1, 2, 3::Int]"three: 1, 2, 3"If the second argument is a null collection then no output is generated for it. sayableA helper operator that generates a sayable from a foldable group (e.g. list) of sayable items. This helper is linke the   operator except that the folded output is immediately adjacent to the preceeding sayable output instead of separated by a space; this is useful for situations where the folded output has delimiters like parentheses or brackets.7sez @"info" $ t'"three:" &- '(' &+* [1,2,3::Int] &+ ')'"three: (1, 2, 3)"If the second argument is an empty collection then no output is generated for it.sayableA helper operator that generates a sayable from a list of sayable items, separated by the first sayable argument (instead of the ", " that use used by the   operator).5sez @"info" $ t'"three:" &- t'".." &:* [1, 2, 3::Int]"three: 1..2..3"sayable/A helper operator that is a combination of the   and   operators. It applies the first argument (which converts an array of 'Prettyprinter.Doc ann' elements into a single 'PrettyPrinter.Doc ann' element) to the second argument (which is a Foldable collection of  items).sez @"info" $ t'"three:" &- PP.align . PP.vsep &!* [1, 2, 3::Int]""three: 1, \n 2, \n 3"sayableA helper operator that applies the first argument (a Prettyprinter adaptation function) to the result of a Foldable collection of 3 items. This is essentially a combination of the   and   operators where the first operation is applied to the entire list, rather than each element of the list (as with ).8sez @"info" $ t'"three:" &- PP.align &!$* [1, 2, 3::Int]"three: 1, 2, 3" As with the  operator (and unlike the   operator), a null collection is passed to the converter first argument.@since: 1.1.0.0sayableA helper operator that applies the first argument (which converts an array of 'Prettyprinter.Doc ann' elements to a single 'PrettyPrinter.Doc ann' element) to the second argument, which is a Foldable collection of 3 items. This is essentially a combination of the   and  operators.Unlike the other operators defined in this package, this is a trinary operator rather than a binary operator. Because function application (whitespace) is the highest precedence, the last argument will typically need a preceeding $ to prevent applying the second argument to the third argument before applying this operator.sez @"info" $ t'"three:" &- (PP.align . PP.vsep &!:* (t'" or")) [1, 2, 3::Int]$"three: 1 or\n 2 or\n 3"sayable>A helper operator allowing a Sayable item to be wrapped in a C. This adds the  of the first argument to the  of the second argument in the D case, or just emits the 2 of the first argument if the second argument is E.sez @"info" $ t'"It's" &? Just (t'"something") &- t'"or" &? (Nothing :: Maybe Text)"It's something or"sayable=A helper operator allowing a Sayable item to be wrapped in a C and a prettyprinter conversion as the first argument. This is a combination of the   and  operators.(sez @"info" $ PP.group &!? Just (t'"hi")"hi"@since: 1.1.0.0sayableA helper operator that generates a newline between its two arguments. Many times the  operator is a better choice to allow normal prettyprinter layout capabilities, but in situations where it is known that multiple lines will or should be generated, this operator makes it easy to separate the lines.$sez @"info" $ t'"Hello" &< t'"world""Hello\nworld"@since: 1.1.0.0sayable A helper operator that combines  and   which will generate a newline between its two arguments, where the second argument is a foldable collection whose elements will be sayable emitted with comma separators.+sez @"info" $ t'"three:" &<* [1, 2, 3::Int]"three:\n1, 2, 3"@since: 1.1.0.0sayableA helper operator that emits the first argument and optionally emits a newline and the D= value of the second argument if the second argument is not E (a combination of the  and  operators).0sez @"info" $ t'"First" & Sayable saytag Foo where ...If there are other constraints that should also be included, those can be specified in a standard constraint tuple: instance ( $(sayableSubConstraints $ ofType ''Baz) , Show Bar ) => Sayable tag Foo where ... The  function will examine the definition of the type referenced by the second argument, and for every sub-type referenced (that is accepted by any ! specified), it will generate a Sayable constraint for the sub type(s). data Bar = ... data Baz = ... data Foo = Foo { fld1 :: Bar , fld2 :: [Baz] , fld3 :: Maybe Bar } instance $(sayableSubConstraints $ do ofType ''Foo tagVar "stag" ) => Sayable stag Foo where sayable foo = ... ,becomes (via the magic of Template Haskell): instance ( Sayable stag Bar , Sayable stag Baz ) => Sayable stag Foo where sayable foo = ... The !  operation can be used to select only a subset of the sub-elements for this constraints generation. For example, with the following definition: :data Foo2 = FC1 Bar [Maybe Baz] | FC2 Bar Int HiddenValue The Sayable instance for Foo2 does not need a tag-specific constraint for the Int type, and the instance will not output the fld5 hidden value, so no  instance constraint is needed (and in fact, for safety, no actual # instance will ever be created for  HiddenValue?). To support this, a filtering function can be used for the Language.Haskell.TH.Name type references: module MyModule where import qualified Language.Haskell.TH as TH data Bar = ... data Baz = ... data HiddenValue = ... data Foo2 = FC1 Bar [Baz] | FC2 (Maybe Bar) Int HiddenValue foo2Filter :: TH.Name -> Bool foo2Filter nm = and [ "HiddenValue" /= TH.nameBase nm , maybe False ("MyModule" ==) $ TH.nameModule nm ] instance $(sayableSubConstraints $ do ofType ''Foo2 tagVar "t" subElemFilter foo2Filter ) => Sayable t Foo2 where sayable = case FC1 x y -> "First Foo2 form with" &- x &- "and" &- y FC2 x y h -> "Second Foo2 form with" &? x &- y instance Sayable t Bar where ... instance Sayable t Baz where ... which generates: instance ( Sayable t Bar, Sayable t Baz ) => Sayable t Foo2 where ... When the sub-elements are themselves parameterized, it is necessary to specify what those parameters should map to: either the same parameter variables that occur on the main type, or other types or values based on the usage of the main type. This can be done using the ", #, $, or %  operations. Each of these param declarations specifies one of the parameters for sub-elements. All sub-elements must specify the parameters in the same order, although each does not need to use all of the parameters; sub-element types that do not follow this arrangement will need to be manually specified instead (and filtered out of the template-haskell generated constraints via the !). data Bar a = Bar (Maybe a) data Baz a b = BazL a | BazR b data Foo3 a = Foo3 { inputs :: Bar a, outputs :: Baz a String } instance $(sayableSubConstraints $ do ofType ''Foo3 tagVar "t" paramVar "a" paramTH $ TH.ConT ''String ) => Sayable t (Foo3 a) where ... generates the following: instance ( Sayable t (Bar a), Sayable t (Baz a String), Sayable t a ) => Sayable (Foo3 a) where ... +Clearly, there are some limitations to the  capabilities, so it is not always useable in all situations (e.g. with tuples). The sub-element constraints can and should be manually generated in these situations.$In order to debug the output of the / or otherwise examine its suitability, enable -ddump-splices when compiling.sayableThis ConstrM operation is used to declare the target data type for which the Sayable constraints are to be generated via template-haskell. instance $(sayableSubConstraints $ do { ofType ''Foo; ... }) => Sayable t Foo where!If not used, the default type is ()., which is not likely to be the desired type.sayableThis ConstrM operation is used to declare the name of the saytag variable used to specify the "Saying VAR sub-element" constraints. This should match the variable for the primary instance declaration. instance $(sayableSubConstraints $ do { ...; tagVar "t" }) => Sayable t X where ...0If not used, the default saytag is the variable saytag*. This operation is coincident with the , tagNat, and tagTH> operations and the last such operation will be the one used.sayableThis ConstrM operation is used to declare a Symbol singleton value for the saytag of the sub-element Sayable constraints. This should match the Symbol used for the primary instance declaration. instance $(sayableSubConstraints $ do tagSym "loud" ofType ''X ) => Sayable "loud" X where ... 0If not used, the default saytag is the variable saytag*. This operation is coincident with the , tagNat, and tagTH> operations and the last such operation will be the one used. sayableSometimes the sub-constraints should be wrapped in another type (via a constructor for that type). For example:&@ data WithIndentation a = WInd Int adata Foo { subVal :: Bar }instance $(sayableSubConstraints $ do ofType ''Foo subWrapper (TH.ConT ''WithIndentation) ) => Sayable saytag Foo where sayable foo = FOO &< WInd 2 (subVal foo)!sayableThis ConstrM operation is used to declare a filter to be applied to the sub-elements: only sub-element G4 candidates for which this filter function returns H* will have a Sayable constraint generated. >myModuleNames :: TH.Name -> Bool myModuleNames = maybe False (MyModule ==) . TH.nameModule instance $(sayableSubConstraints $ do ofType ''Foo subElemFilter myModuleNames ) => Sayable saytag Foo where ... *If not used, the default is equivalent to subElemFilter (const True)& which accepts all sub-element names."sayableThis ConstrM operation is used to specify the variable name that should be used for the next sub-element parameter. When sub-elements are parameterized (e.g. Maybe a) then this operation allows the identification of a primary instance variable to be used for the sub-element. All sub-elements must take parameters in the same order, although they don't need to accept all parameters. data Foo b a = Foo (Either a b) instance $(sayableSubConstraints $ do ofType ''Foo paramVar "x" paramVar "y" ) => Sayable saytag (Foo y x) where ...  generates: (Sayable saytag (Either x y), Sayable saytag x, Sayable saytag y)As shown above, this operation can be used multiple times to specify multiple parameters.#sayableThis ConstrM operation is used to specify a Symbol singleton value that should be used for the next sub-element parameter. When sub-elements are parameterized (e.g. Maybe a) then this operation allows the identification of a Symbol to be used for the sub-element. All sub-elements must take parameters in the same order, although they don't need to accept all parameters. data Bar (s :: Symbol) = ... data Foo (s :: Symbol) = Foo { thing :: Bar s } instance $(sayableSubConstraints $ do ofType ''Foo paramSym "arg" ) => Sayable saytag (Foo "arg") where ...  generates: Sayable saytag (Bar "arg")This operation can be used multiple times to specify multiple parameters.$sayableThis ConstrM operation is used to specify a Nat singleton value that should be used for the next sub-element parameter. When sub-elements are parameterized (e.g. Maybe a) then this operation allows the identification of a Nat to be used for the sub-element. All sub-elements must take parameters in the same order, although they don't need to accept all parameters. data Bar (s :: Symbol) (n :: Nat) = ... data Foo (n :: Nat) (s :: Symbol) = Foo { thing :: Bar s n } instance $(sayableSubConstraints $ do ofType ''Foo paramSym "arg" paramNat 2 ) => Sayable saytag (Foo 2 "arg") where ...  generates: Sayable saytag (Bar "arg" 2)This operation can be used multiple times to specify multiple parameters.%sayableThis ConstrM operation is used to specify a template-haskell Type that should be used for the next sub-element parameter. When sub-elements are parameterized (e.g. Maybe a) then this operation allows specification of a specific Type for that parameter. The use of this operation is unusual and is expected only in cases where ", #, or $ are insufficient. data Bar '(s :: Symbol, n :: Nat) = ... data Foo (n :: Nat) (s :: Symbol) = Foo { thing :: Bar '(s, n) } instance $(sayableSubConstraints $ do ofType ''Foo paramTH (TH.App (TH.App (TH.TupleT 2) (TH.LitT $ TH.StrTyLit "loud")) (TH.LitT $ TH.NumTyLit 3)) ) => Sayable saytag (Foo 3 "loud") where ...  generates: !Sayable saytag (Bar '("loud", 3))This operation can be used multiple times to specify multiple parameters.'sayableA Saying can be converted back into a PP.Pretty instance representation. Just saying... :-)This can be convenient to apply Prettyprinter formatting elements. For example: instance Sayable saytag Foo where sayable foo = sayable @saytag $ Prettyprinter.group $ Prettyprinter.pretty $ field1 foo &- sayable @saytag PP.line &- field2 foo This uses  and   formatters to show the two fields on the same line if they will fit, otherwise stacked on top of each other. Note that the second portion needs an explicit TypeApplication (applied here to the  ) because the  and  ' functions do not propagate that outer saytag to the inner portion.>sayableInputs that are (, i.e. that can be converted to a Saying&  !"#$%&   !"#$%1 1 1 2 1 12222111111      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMKNOKNPKNQKRSTUVWXY&sayable-1.2.4.0-FLvGHArOZbm3cWmbFiqvOi Text.Sayable PrettyprinterhcatDocPretty Data.StringIsStringgrouplineprettyConstrM SayableAnnSayingsayingSayablesayable&-&+&%&!&*&+*&:*&!*&!$*&!:*&?&!?&<&<*&