diff --git a/src/Text/HTML/Basic/Character.hs b/src/Text/HTML/Basic/Character.hs
--- a/src/Text/HTML/Basic/Character.hs
+++ b/src/Text/HTML/Basic/Character.hs
@@ -6,6 +6,7 @@
    unicode, refC, refE,
    asciiFromUnicode,
    asciiFromUnicodeInternetExploder,
+   minimalRefFromUnicode,
    reduceRef,
    validCharRef, switchUnicodeRuns,
    isLower, isUpper, toLower, toUpper,
diff --git a/src/Text/HTML/Basic/Tag.hs b/src/Text/HTML/Basic/Tag.hs
--- a/src/Text/HTML/Basic/Tag.hs
+++ b/src/Text/HTML/Basic/Tag.hs
@@ -25,14 +25,14 @@
 {- |
 Check whether a HTML tag is empty.
 -}
-isEmpty :: (Name.Tag name, Ord name) =>
+isEmpty :: (Name.Tag name) =>
    Name name -> Bool
 isEmpty = flip Set.member emptySet
 
 {- |
 Set of empty HTML tags.
 -}
-emptySet :: (Name.Tag name, Ord name) =>
+emptySet :: (Name.Tag name) =>
    Set.Set (Name name)
 emptySet =
    nameSet $
@@ -57,7 +57,7 @@
 We close them implicitly, if another tag closes
 and ignore non-matching closing tags.
 -}
-isSloppy ::  (Name.Tag name, Ord name) =>
+isSloppy ::  (Name.Tag name) =>
    Name name -> Bool
 isSloppy = flip Set.member sloppySet
 
@@ -66,7 +66,7 @@
 http://extremetracking.com/open;unique?login=crsucks
 -}
 
-sloppySet :: (Name.Tag name, Ord name) =>
+sloppySet :: (Name.Tag name) =>
    Set.Set (Name name)
 sloppySet =
    nameSet $
@@ -82,14 +82,14 @@
    []
 
 
-isInnerOf :: (Name.Tag name, Ord name) =>
+isInnerOf :: (Name.Tag name) =>
    Name name -> Name name -> Bool
 isInnerOf outer inner =
    maybe False (Set.member inner) $
    Map.lookup outer innerMap
 
 
-innerMap :: (Name.Tag name, Ord name) =>
+innerMap :: (Name.Tag name) =>
    Map.Map (Name name) (Set.Set (Name name))
 innerMap =
    nameMap $
@@ -114,7 +114,7 @@
    []
 
 
-closes :: (Name.Tag name, Ord name) =>
+closes :: (Name.Tag name) =>
    Name name -> Name name -> Bool
 closes closing opening =
    (not (Name.match "option" closing) && Name.match "select" opening) ||
@@ -123,7 +123,7 @@
     Map.lookup closing closesMap)
 
 
-closesMap :: (Name.Tag name, Ord name) =>
+closesMap :: (Name.Tag name) =>
    Map.Map (Name name) (Set.Set (Name name))
 closesMap =
    nameMap $
@@ -158,17 +158,17 @@
    []
 
 
-nameMap :: (Name.Tag name, Ord name) => [(String,a)] -> Map.Map (Name name) a
+nameMap :: (Name.Tag name) => [(String,a)] -> Map.Map (Name name) a
 nameMap = Map.fromList . map (mapFst Name.fromString)
 
-nameSet :: (Name.Tag name, Ord name) => [String] -> Set.Set (Name name)
+nameSet :: (Name.Tag name) => [String] -> Set.Set (Name name)
 nameSet = Set.fromList . map Name.fromString
 
-nameSingle :: (Name.Tag name, Ord name) => String -> Set.Set (Name name)
+nameSingle :: (Name.Tag name) => String -> Set.Set (Name name)
 nameSingle = Set.singleton . Name.fromString
 
 pSet, dtdSet, thdSet, thdrSet, liSet, headingSet ::
-   (Name.Tag name, Ord name) => Set.Set (Name name)
+   (Name.Tag name) => Set.Set (Name name)
 pSet       = nameSet ["p"]
 dtdSet     = nameSet ["dt","dd"]
 thdSet     = nameSet ["th","td"]
diff --git a/src/Text/XML/Basic/Attribute.hs b/src/Text/XML/Basic/Attribute.hs
--- a/src/Text/XML/Basic/Attribute.hs
+++ b/src/Text/XML/Basic/Attribute.hs
@@ -77,8 +77,8 @@
 
 
 
-mapName :: (name0 -> name1) -> T name0 string -> T name1 string
-mapName f (Cons (Name n) v) = Cons (Name $ f n) v
+mapName :: (Name name0 -> Name name1) -> T name0 string -> T name1 string
+mapName f (Cons n v) = Cons (f n) v
 
 
 
@@ -130,7 +130,7 @@
 
 
 insert ::
-   (Name.Attribute name, Eq name) =>
+   (Name.Attribute name) =>
    Name name ->
    string ->
    ([T name string] -> [T name string])
@@ -143,7 +143,7 @@
 The function name is analogous to Data.Map.
 -}
 insertWith ::
-   (Name.Attribute name, Eq name) =>
+   (Name.Attribute name) =>
    (string -> string -> string) ->
    Name name ->
    string ->
@@ -158,7 +158,7 @@
 -- * match attributes
 
 match ::
-   (Name.Attribute name, Eq name, Eq string) =>
+   (Name.Attribute name, Eq string) =>
    String -> string -> T name string -> Bool
 match n v attr =
    Name.match n (name_ attr) && v == value_ attr
@@ -170,21 +170,21 @@
 The values are handled case-sensitive.
 -}
 matchAnyValue ::
-   (Name.Attribute name, Eq name, Eq string) =>
+   (Name.Attribute name, Eq string) =>
    String -> [string] -> T name string -> Bool
 matchAnyValue n vs attr =
    Name.match n (name_ attr) && elem (value_ attr) vs
 
 
 lookup ::
-   (Name.Attribute name, Eq name) =>
+   (Name.Attribute name) =>
    Name name -> [T name string] -> Maybe string
 lookup n =
    fmap value_ .
    List.find ((n==) . name_)
 
 lookupLit ::
-   (Name.Attribute name, Eq name) =>
+   (Name.Attribute name) =>
    String -> [T name string] -> Maybe string
 lookupLit n =
    fmap value_ .
@@ -202,12 +202,12 @@
 
 
 anyLit ::
-   (Eq name, Name.Attribute name, Eq string) =>
+   (Name.Attribute name, Eq string) =>
    String -> string -> [T name string] -> Bool
 anyLit n v = any (match n v)
 
 anyNameLit ::
-   (Eq name, Name.Attribute name) =>
+   (Name.Attribute name) =>
    String -> [T name string] -> Bool
 anyNameLit n = anyName (Name.match n)
 
diff --git a/src/Text/XML/Basic/Character.hs b/src/Text/XML/Basic/Character.hs
--- a/src/Text/XML/Basic/Character.hs
+++ b/src/Text/XML/Basic/Character.hs
@@ -17,7 +17,7 @@
    maybeUnicode, maybeCharRef, maybeEntityRef,
    isUnicode, isCharRef, isEntityRef, isRef,
    unicode, refC, refE,
-   asciiFromUnicode, asciiFromUnicodeGen,
+   asciiFromUnicode, asciiFromUnicodeGen, minimalRefFromUnicode,
    reduceRef, reduceRefGen,
    validCharRef, switchUnicodeRuns,
    ) where
@@ -112,7 +112,9 @@
 
 
 {-|
-Convert unicode character to XML Char.
+Convert unicode character to XML Char,
+where Unicode constructor is only used for ASCII characters.
+This is achieved by the following decision:
 If there is a entity reference, use this.
 If it is ASCII, represent it as Char.
 Otherwise use a character reference.
@@ -131,6 +133,20 @@
    Map.lookup c dict
 
 
+{- |
+Generate XML character from Unicode character
+with minimal use of references.
+The only references used are the XML entity references
+@&apos;@, @&quot;@, @&amp;@, @&lt;@, @&gt;@.
+-}
+minimalRefFromUnicode :: Char -> T
+minimalRefFromUnicode c =
+   maybe
+      (fromUnicode c)
+      fromEntityRef $
+   Map.lookup c Ent.mapCharToName
+
+
 -- * shortcuts for making the output of the Show instance valid
 
 unicode :: Char -> T
@@ -175,12 +191,17 @@
 
 
 instance Fmt.C T where
-   run (Unicode c) = (c:)
+   run (Unicode c) = showChar c
    run (CharRef n) = Fmt.amp . Fmt.sharp . shows n . Fmt.semicolon
-   run (EntityRef n) = Fmt.amp . (n++) . Fmt.semicolon
+   run (EntityRef n) = Fmt.amp . showString n . Fmt.semicolon
 
 
 
+{- |
+Reduce the use of references.
+Represent as much as possible characters as Unicode characters,
+that is, using the Unicode constructor.
+-}
 reduceRef :: T -> T
 reduceRef = reduceRefGen Ent.mapNameToChar
 
diff --git a/src/Text/XML/Basic/Format.hs b/src/Text/XML/Basic/Format.hs
--- a/src/Text/XML/Basic/Format.hs
+++ b/src/Text/XML/Basic/Format.hs
@@ -1,6 +1,8 @@
 module Text.XML.Basic.Format where
 
 import qualified Text.XML.Basic.Name as Name
+import qualified Text.XML.Basic.Entity as Ent
+import qualified Data.Map as Map
 
 import Prelude hiding (quot)
 
@@ -9,7 +11,18 @@
    run :: object -> ShowS
 
 instance C Char where
+   run c =
+      maybe
+         (showChar c)
+         (\n -> amp . showString n . semicolon) $
+      Map.lookup c Ent.mapCharToName
+
+{- that one causes cyclic module dependencies
+   run = run . XMLChar.minimalRefFromUnicode
+-}
+{- that one is too simple - we always have to emit valid XML code
    run = showChar
+-}
 
 instance C object => C [object] where
    run = many run
diff --git a/src/Text/XML/Basic/Name.hs b/src/Text/XML/Basic/Name.hs
--- a/src/Text/XML/Basic/Name.hs
+++ b/src/Text/XML/Basic/Name.hs
@@ -8,7 +8,7 @@
 
 -- * types and classes
 
-class C name where
+class Ord name => C name where
    fromString :: String -> name
    toString :: name -> String
 
@@ -18,11 +18,11 @@
 because DOCTYPE as tag name must be written upper case,
 whereas as attribute name it may be written either way.
 -}
-class Tag ident where
+class Ord ident => Tag ident where
    tagFromString :: String -> ident
    tagToString :: ident -> String
 
-class Attribute ident where
+class Ord ident => Attribute ident where
    attributeFromString :: String -> ident
    attributeToString :: ident -> String
 
@@ -30,8 +30,8 @@
 
 -- * convenience functions
 
-match :: (C name, Eq name) => String -> name -> Bool
+match :: (C name) => String -> name -> Bool
 match proto = (fromString proto ==)
 
-matchAny :: (C name, Eq name) => [String] -> name -> Bool
+matchAny :: (C name) => [String] -> name -> Bool
 matchAny proto = flip elem (map fromString proto)
diff --git a/src/Text/XML/Basic/ProcessingInstruction.hs b/src/Text/XML/Basic/ProcessingInstruction.hs
--- a/src/Text/XML/Basic/ProcessingInstruction.hs
+++ b/src/Text/XML/Basic/ProcessingInstruction.hs
@@ -46,8 +46,11 @@
          Known attrs  -> liftA Known $ traverse sequenceA attrs
          Unknown text -> pure $ Unknown text
 
-mapName :: (name0 -> name1) -> T name0 string -> T name1 string
-mapName f = mapAttributes (map (Attr.mapName f))
+mapName ::
+   (Attr.Name name0 -> Attr.Name name1) ->
+   T name0 string -> T name1 string
+mapName f =
+   mapAttributes (map (Attr.mapName f))
 
 
 mapAttributes ::
diff --git a/xml-basic.cabal b/xml-basic.cabal
--- a/xml-basic.cabal
+++ b/xml-basic.cabal
@@ -1,5 +1,5 @@
 Name:             xml-basic
-Version:          0.0.1
+Version:          0.1
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -25,7 +25,7 @@
 Source-Repository this
   type:     darcs
   location: http://code.haskell.org/~thielema/xml-basic/
-  tag:      0.0.1
+  tag:      0.1
 
 Flag splitBase
   description: Choose the new smaller, split-up base package.
