diff --git a/Language/TEval/TInfT.hs b/Language/TEval/TInfT.hs
--- a/Language/TEval/TInfT.hs
+++ b/Language/TEval/TInfT.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE PatternGuards #-}
 -- | Simply-typed Curry-style (nominal) lambda-calculus
 -- with integers and zero-comparison
 -- Type inference
diff --git a/Text/GenPrintF.hs b/Text/GenPrintF.hs
new file mode 100644
--- /dev/null
+++ b/Text/GenPrintF.hs
@@ -0,0 +1,120 @@
+
+-- | 
+--
+-- <http://okmij.org/ftp/typed-formatting/FPrintScan.html#print-show>
+--
+--
+-- Generic polyvariadic printf in Haskell98
+-- 
+-- This generalization of Text.Printf.printf is inspired by the message of Evan Klitzke, who wrote
+-- on Haskell-Cafe about frequent occurrences in his code of the lines like
+-- 
+-- >        infoM $ printf "%s saw %s with %s" (show x) (show y) (show z)
+-- 
+-- Writing show on and on quickly becomes tiresome. It turns out, we can avoid these repeating show,
+-- still conforming to Haskell98.
+-- 
+-- Our polyvariadic generic printf is like polyvariadic show with the printf-like format string. Our
+-- printf handles values of any present and future type for which there is a Show instance. For
+-- example:
+-- 
+-- >        t1 = unR $ printf "Hi there"
+-- >        -- "Hi there"
+-- 
+-- >        t2 = unR $ printf "Hi %s!" "there"
+-- >        -- "Hi there!"
+-- 
+-- >        t3 = unR $ printf "The value of %s is %s" "x" 3
+-- >        -- "The value of x is 3"
+-- 
+-- >        t4 = unR $ printf "The value of %s is %s" "x" [5]
+-- >        -- "The value of x is [5]"
+-- 
+-- The unsightly unR appears solely for Haskell98 compatibility: flexible instances remove the need
+-- for it. On the other hand, Evan Klitzke's code post-processes the result of formatting with
+-- infoM, which can subsume unR.
+-- 
+-- A bigger problem with our generic printf, shared with the original Text.Printf.printf, is
+-- partiality: The errors like passing too many or too few arguments to printf are caught only at
+-- run-time. We can certainly do better.
+-- 
+-- Version:  The current version is 1.1, June 5, 2009.
+--
+-- References
+--
+--  *  The complete source code with the tests. It was published in the message posted on the
+--     Haskell-Cafe mailing list on Fri, 5 Jun 2009 00:57:00 -0700 (PDT)
+--     <http://okmij.org/ftp/typed-formatting/GenPrintF.hs>
+-- 
+
+module Text.GenPrintF where
+
+-- | Needed only for the sake of Haskell98
+-- If we are OK with flexible instances, this newtype can be disposed of
+newtype RString = RString{unR:: String} 
+
+class SPrintF r where
+    pr_aux :: [FDesc] -> [String] -> r
+
+-- | These two instances are all we ever need
+
+instance SPrintF RString where
+    pr_aux desc acc = RString . concat . reverse $ foldl f acc desc
+     where
+     f acc (FD_lit s) = s : acc
+     f acc FD_str     = error "Unfulfilled %s formatter"
+
+instance (Show a, SPrintF r) => SPrintF (a->r) where
+    pr_aux desc acc x = pr_aux desc' acc'
+     where
+     (desc',acc') = fmtx desc acc
+     fmtx [] acc     = error "No formatting directive for the argument"
+     fmtx (FD_lit s:desc) acc = fmtx desc (s:acc)
+     fmtx (FD_str : desc) acc = (desc, unq (show x) : acc)
+     unq ('"' : str) | last str == '"' = init str
+     unq str  = str
+
+
+printf str = pr_aux (convert_to_fdesc str) []
+
+-- tests
+
+t1 = unR $ printf "Hi there"
+-- "Hi there"
+
+t2 = unR $ printf "Hi %s!" "there"
+-- "Hi there!"
+
+t3 = unR $ printf "The value of %s is %s" "x" 3
+-- "The value of x is 3"
+
+t4 = unR $ printf "The value of %s is %s" "x" [5]
+-- "The value of x is [5]"
+
+
+
+-- | A very simple language of format descriptors
+data FDesc = FD_lit String | FD_str deriving (Eq, Show)
+
+-- Convert "insert %s here" into 
+-- [FD_lit "insert ", FD_str, FD_lit " here"]
+convert_to_fdesc :: String -> [FDesc]
+convert_to_fdesc str = 
+    case break (=='%') str of
+      (s1,"") -> make_lit s1
+      (s1,'%':'s':rest) -> make_lit s1 ++ FD_str : convert_to_fdesc rest
+      (_,s2) -> error $ "bad descriptor: " ++ take 5 s2
+ where
+ make_lit "" = []
+ make_lit str = [FD_lit str]
+
+test_cvf = and [
+    convert_to_fdesc "Simple lit" ==
+       [FD_lit "Simple lit"],
+    convert_to_fdesc "%s insert" ==
+       [FD_str,FD_lit " insert"],
+    convert_to_fdesc "insert %s here" ==
+    [FD_lit "insert ",FD_str,FD_lit " here"]
+    ]
+
+
diff --git a/Text/TFTest.hs b/Text/TFTest.hs
new file mode 100644
--- /dev/null
+++ b/Text/TFTest.hs
@@ -0,0 +1,119 @@
+{-# LANGUAGE TemplateHaskell, NoMonomorphismRestriction #-}
+-- The rest is Haskell98
+
+-- | Type-safe printf and scanf with C-like formatting string
+-- We also permit a generic format specifier %a to format or parse
+-- any showable and readable value.
+-- Our format descriptors are first-class and can be built incrementally.
+-- We can use the same format descriptor to format to a string,
+-- to the standard output or any other data sink. Furthermore,
+-- we can use the same format descriptor to parse from a string
+-- or any data source.
+-- What we print we can parse, using the same descriptor.
+
+module Text.TFTest where
+
+import Text.TotalPrintF
+import Prelude hiding ((^))
+
+-- The following import is needed only for the extensibility test
+-- at the end of the file
+import Text.PrintScanF (FormattingSpec(..), PrinterParser(..)) 
+
+t1 = sprintf $(spec "Hello, there!")
+-- "Hello, there!"
+
+t1s = sscanf "Hello, there!" $(spec "Hello, there!") ()
+-- Just ()
+
+t2 = sprintf $(spec "Hello, %s!") "there"
+-- "Hello, there!"
+
+t3 = sprintf $(spec "The value of %s is %d") "x" 3
+-- "The value of x is 3"
+
+-- What we print we can parse, using the same descriptor
+t31 = let printed = sprintf desc "x" 3
+          parsed  = sscanf printed desc (\s i -> (s,i))
+      in (printed, parsed)
+  where desc = $(spec "The value of %s is %d")
+-- ("The value of x is 3",Just ("x",3))
+
+-- Mismatch between the formatting string and the printf arguments
+-- is a type error.
+
+-- t32 = sprintf $(spec "The value of %s is %d") "x" True
+--     Couldn't match expected type `Bool' against inferred type `Int'
+
+{-
+t33 = sprintf $(spec "The value of %s is %d") "x" 3 10
+    Couldn't match expected type `t1 -> t'
+           against inferred type `String'
+    Probable cause: `printf' is applied to too many arguments
+-}
+
+t4 = let x = [9,16,25] 
+	 i = 2 
+     in sprintf $(spec "The element number %d of %a is %a") i x (x !! i)
+-- "The element number 2 of [9,16,25] is 25"
+
+t4s = sscanf "The element number 2 of [9,16,25] is 25"
+        $(spec "The element number %d of %a is %a")
+        (\i a e -> (i,a::[Int],e::Int))
+-- Just (2,[9,16,25],25)
+
+
+
+-- Demonstrating that printf is first-class
+t5 = map (uncurry printer) [("x",3), ("y",5), ("z",7)]
+ where
+ printer = sprintf $(spec "The value of %s is %d")
+
+-- ["The value of x is 3","The value of y is 5","The value of z is 7"]
+
+{- An inconsistent format descriptor generates a type error
+
+t6 = map (uncurry printer) [("x",3), ("y",5), ("z",7)]
+ where
+ printer = sprintf $(spec "The value of %d is %d")
+    Couldn't match expected type `Int' against inferred type `[Char]'
+    In the expression: "x"
+    In the expression: ("x", 3)
+    In the second argument of `map', namely
+        `[("x", 3), ("y", 5), ("z", 7)]'
+
+-}
+
+-- Demonstrating that format descriptors are first-class and can be built 
+-- incrementally
+
+spec71 = $(spec "The value of %s")
+spec72 = $(spec " is %d")
+t7 = sprintf (spec71 ^ spec72) "x" 3
+-- "The value of x is 3"
+
+
+-- Extensibility test
+
+-- Furthermore, the user can always extend printf, for example, to
+-- send the formatted data to the standard output, without first building
+-- the formatted output as a string.
+
+
+newtype FPrIO a b = FPrIO ((IO () -> a) -> b)
+
+instance FormattingSpec FPrIO where
+    lit str = FPrIO $ \k -> k $ putStr str
+    int     = FPrIO $ \k -> \x -> k $ putStr (show x)
+    char    = FPrIO $ \k -> \x -> k $ putStr [x]
+    fpp (PrinterParser pr _) = FPrIO $ \k -> \x -> k $ putStr (pr x)
+    (FPrIO a) ^ (FPrIO b)  = FPrIO $ \k -> a (\sa -> b (\sb -> k (sa >> sb)))
+
+printf (FPrIO fmt) = fmt (\m -> m >> putStrLn "\n-end-of-output-")
+
+t3io = printf $(spec "The value of %s is %d") "x" 3
+{- printed on the standard output:
+
+The value of x is 3
+-end-of-output-
+-}
diff --git a/Text/TotalPrintF.hs b/Text/TotalPrintF.hs
new file mode 100644
--- /dev/null
+++ b/Text/TotalPrintF.hs
@@ -0,0 +1,133 @@
+{-# LANGUAGE TemplateHaskell #-}
+-- The rest is Haskell98
+
+-- |
+--
+-- <http://okmij.org/ftp/typed-formatting/FPrintScan.html#C-like>
+--
+-- Safe and generic printf/scanf with C-like format string
+-- 
+-- We implement printf that takes a C-like format string and the variable number
+-- of other arguments.  Unlike C of Haskell's printf, ours is total: if the types
+-- or the number of the other arguments, the values to format, does not match the
+-- format string, a type error is reported at compile time.  To the familiar
+-- format descriptors %s and %d we add %a to format any showable value. The latter
+-- is like the format descriptor ~a of Common Lisp. Likewise, we build scanf that
+-- takes a C-like format string and the consumer function with the variable number
+-- of arguments. The types and the number of the arguments must match the format
+-- string; a type error is reported otherwise.
+-- 
+-- Our approach is a variation of the safe printf and scanf described
+-- elsewhere on this page. We use Template Haskell to translate the format string
+-- to a phrase in the DSL of format descriptors. We use the final approach to
+-- embed that DSL into Haskell.
+-- 
+-- Unlike the safe printf explained in the Template Haskell documentation, in
+-- our implementation, format descriptors are first class. They can be built
+-- incrementally. The same descriptor can be used both for printing and for
+-- parsing. Our printf and scanf are user-extensible: library users can write
+-- functions to direct format output to any suitable data sink, or to read parsed
+-- data from any suitable data source such as string or a file. Finally, what is
+-- formatted can be parsed back using the same format descriptor.
+-- 
+-- Here are some of the tests from the test collection referenced below. The
+-- evaluation result is given in the comments below each binding. Example t31
+-- shows that format descriptors are indeed first-class. The definition t32, when
+-- uncommented, raises the shown type error because the format descriptor does not
+-- match the type of the corresponding argument.
+--
+
+-- Type-safe printf and scanf with C-like formatting string
+-- We also permit a generic format specifier %a to format or parse
+-- any showable and readable value.
+--
+-- Our format descriptors are first-class and can be built incrementally.
+-- We can use the same format descriptor to format to a string,
+-- to the standard output or to any other data sink. Furthermore,
+-- we can use the same format descriptor to parse from a string
+-- or any data source.
+-- What we print we can parse, using the same descriptor.
+--
+-- We rely on Template Haskell to convert the format string into
+-- the phrase of the DSL for format descriptors.
+-- We use the Final approach to embed that DSL into Haskell, see
+-- PrintScanF.hs
+--
+-- Unlike the safe printf described in the Template Haskell
+-- documentation, our format descriptors are first class.
+-- They can be built incrementally. They can be used both
+-- for printing and for parsing. Our printf and scanf are user-extensible:
+-- library users can write functions to direct format output to any
+-- suitable data sink, or to read parsed data from any suitable
+-- data source.
+-- Please see the examples in the file TFTest.hs.
+
+module Text.TotalPrintF (spec, sprintf, sscanf, (^)) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax
+import Language.Haskell.TH.Ppr
+import Prelude hiding ((^))
+
+import Text.PrintScanF			-- EDSL of format descriptors
+
+-- | Primitive format descriptors used here
+str :: (FormattingSpec repr) => repr w (String -> w)
+str  = fpp (PrinterParser id parse)
+ where
+ parse s = Just $ break (== ' ') s	-- the behavior of %s in C
+
+anys :: (FormattingSpec repr, Show a, Read a) => repr w (a -> w)
+anys = fpp showread
+
+-- | Converting from formatting strings to format descriptors
+fdesc_to_code :: [FDesc] -> ExpQ
+fdesc_to_code [d] = cnv1 d
+fdesc_to_code (d:desc) = [e| $(cnv1 d) ^ $(fdesc_to_code desc)|]
+
+cnv1 (FD_lit str) = [e| lit str|]
+cnv1 FD_int       = [e| int  |]
+cnv1 FD_str       = [e| str  |]
+cnv1 FD_any       = [e| anys |]
+
+spec :: String -> ExpQ
+spec = fdesc_to_code . convert_to_fdesc
+
+show_code cde = runQ cde >>= putStrLn . pprint
+
+tc1 = show_code . spec $ "abc"
+-- PrintScanF.lit ['a', 'b', 'c']
+
+tc2 = show_code . spec $ "Hello %s!"
+-- PrintScanF.lit "Hello " PrintScanF.^ 
+--       (TotalPrintF.str PrintScanF.^ PrintScanF.lit ['!'])
+
+
+-- A very simple language of format descriptors
+
+data FDesc = FD_lit String | FD_str | FD_int | FD_any deriving (Eq, Show)
+
+-- Convert "insert %s here" into 
+-- [FD_lit "insert ", FD_str, FD_lit " here"]
+convert_to_fdesc :: String -> [FDesc]
+convert_to_fdesc str = 
+    case break (=='%') str of
+      (s1,"") -> make_lit s1
+      (s1,'%':'s':rest) -> make_lit s1 ++ FD_str : convert_to_fdesc rest
+      (s1,'%':'a':rest) -> make_lit s1 ++ FD_any : convert_to_fdesc rest
+      (s1,'%':'d':rest) -> make_lit s1 ++ FD_int : convert_to_fdesc rest
+      (_,s2) -> error $ "bad descriptor: " ++ take 5 s2
+ where
+ make_lit "" = []
+ make_lit str = [FD_lit str]
+
+test_cvf = and [
+    convert_to_fdesc "Simple lit" ==
+       [FD_lit "Simple lit"],
+    convert_to_fdesc "%s insert" ==
+       [FD_str,FD_lit " insert"],
+    convert_to_fdesc "insert %s here" ==
+    [FD_lit "insert ",FD_str,FD_lit " here"],
+    convert_to_fdesc "The value of %s is %d" ==
+    [FD_lit "The value of ",FD_str,FD_lit " is ",FD_int]
+    ]
diff --git a/liboleg.cabal b/liboleg.cabal
--- a/liboleg.cabal
+++ b/liboleg.cabal
@@ -1,5 +1,5 @@
 name:           liboleg
-version:        0.1.1
+version:        0.2
 license:        BSD3
 license-file:   LICENSE
 author:         Oleg Kiselyov
@@ -17,7 +17,8 @@
             base < 4,
             containers,
             mtl,
-            unix
+            unix,
+            template-haskell
 
     exposed-modules:
             Data.FDList
@@ -42,6 +43,9 @@
 
             Text.PrintScan
             Text.PrintScanF
+            Text.GenPrintF
+            Text.TotalPrintF
+            Text.TFTest
 
             System.SysOpen
             System.IterateeM
