úÎ9ú8     (C) 2016 Csongor KissBSD3*Csongor Kiss <kiss.csongor.kiss@gmail.com> experimentalportableSafe'(345;>KLNU:Then fold the list into its final form, the format String.:Essentially map PrintfFormat over the Template's [Format].ƒUnfortunately we don't have support for unsaturated type family applications, so the recursion has to be written out explicitly :(KConvert from the Haskell type representation to the printf format notation.GWe map the appropriate types to their corresponding specifiers, such as#String -> %s Int -> %d etc ...$TODO: this is incomplete (or is it?)/Construct the type of the final printf function Acts like a cons function for š lists, first turning the the new head element into a Format. (since it can be a string literal (kind Symbol), for example, or a Haskell type (kind *)). Because the p type family is poly-kinded, it supports both lists and singular format specifiers. Composition produces lists. [format :: Template (Int % "in base 16 is: " % 'Hex) format = Template printf format 50 50 Type-level list appendVType family that produces a proxy (Template') from any compatible template candidate.@This way, we can have produce templates from single types, as in Template :: Template Intwhich acts as a `%d' specifier, or !Template :: Template ('Hex % Int):which is a "%x %d" format string. (see composition below).;Fixed-kinded proxy for storing a list of Formats for printf½Format specifiers that are not directly tied to a type. For example, Hex (%x) belongs here, but Int (%d) doesn't. These constructors are used ticked, promoting FormatSpec to its own kind.%x (requires an Int)%b (requires an Int)%o (requires an Int)%e (requires a Double) Composes two templates.pGiven two terms representing templates, simply appends them to produce a new term representing the composition. Žformat :: Template (Int % " in base " % Int % " is: ") format = Template hex :: Template 'Hex hex = Template printf (format % hex) 30 16 30 (which yields the same result as calling  as such: 2Text.Printf.printf "%d in base %d is: %x" 30 16 30 <Same as (%), but inserts a space in between the two formats. The printf frontend.aœ is of kind [Format]. It is first turned into a list of format specifiers (the literals are kept in place), then the format string is constructed from it.Example: Nprintf (Template :: Template ("hex: " % 'Hex % " binary: " % 'Binary)) 500 500Hgenerates a format string "hex: %x binary: %b", and calls the internal 3 with the format string and the provided arguments. LTerm-level representation of a 'Hex (hexadecimal) specifier for composition.Example:  printf hex 35 GTerm-level representation of an 'Oct (octal) specifier for composition.LTerm-level representation of an 'Sci (scientific) specifier for composition.ATerm-level representation of a 'Binary specifier for composition.@Term-level representation of a String specifier for composition.wThis will not generate string literals in the format string (as that's only possible at the type-level), but insert a `%s'u specifier and modify the type of printf accordingly, so it is useful when the string is not known at compile time.Example: printf string "example"&This means this is the same as calling !Text.Printf.printf "%s" "example"$ :Witness the Format list. The proxy is usually a Template'.The constructed type for printf !"#    !"# $      !"#$%print_JLXec7CNQ4LL0w2KgSdlFgText.Printf.Safe Text.Printfprintf%Template Template' FormatSpecHexBinaryOctSci<%>hexoctscibinarystring FoldToString FormatList PrintfFormat PrintfTypeFormat:++ foldToString FormatTypeToFormatInternalFormatILit ISpecifierLit TypeSpecifierCustomSpecifier formatString$fFoldToString[]:$fFoldToString[]:0$fFoldToString[][]