diff --git a/gnuplot.cabal b/gnuplot.cabal
--- a/gnuplot.cabal
+++ b/gnuplot.cabal
@@ -1,5 +1,5 @@
 Name:             gnuplot
-Version:          0.3.4
+Version:          0.4
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -96,20 +96,25 @@
     Graphics.Gnuplot.Frame.OptionSet
     Graphics.Gnuplot.Plot.TwoDimensional
     Graphics.Gnuplot.Plot.ThreeDimensional
+    Graphics.Gnuplot.Graph
     Graphics.Gnuplot.Graph.TwoDimensional
     Graphics.Gnuplot.Graph.ThreeDimensional
     Graphics.Gnuplot.LineSpecification
     Graphics.Gnuplot.MultiPlot
+    Graphics.Gnuplot.Value.Atom
+    Graphics.Gnuplot.Value.Tuple
+    Graphics.Gnuplot.Value.ColumnSet
   Other-Modules:
     Graphics.Gnuplot.Private.LineSpecification
     Graphics.Gnuplot.Private.Plot
     Graphics.Gnuplot.Private.Frame
     Graphics.Gnuplot.Private.FrameOption
     Graphics.Gnuplot.Private.FrameOptionSet
-    Graphics.Gnuplot.Private.GraphType
     Graphics.Gnuplot.Private.Graph
     Graphics.Gnuplot.Private.Graph2D
     Graphics.Gnuplot.Private.Graph3D
+    Graphics.Gnuplot.Private.Graph2DType
+    Graphics.Gnuplot.Private.Graph3DType
     Graphics.Gnuplot.Private.GraphEmpty
     Graphics.Gnuplot.Utility
     Graphics.Gnuplot.Execute
diff --git a/src/Demo.hs b/src/Demo.hs
--- a/src/Demo.hs
+++ b/src/Demo.hs
@@ -9,65 +9,109 @@
 import qualified Graphics.Gnuplot.Frame.Option as Opt
 import qualified Graphics.Gnuplot.Frame.OptionSet as Opts
 
+import qualified Graphics.Gnuplot.Graph as Graph
+
 import qualified Graphics.Gnuplot.Plot.ThreeDimensional as Plot3D
+import qualified Graphics.Gnuplot.Graph.ThreeDimensional as Graph3D
 
 import qualified Graphics.Gnuplot.Plot.TwoDimensional as Plot2D
 import qualified Graphics.Gnuplot.Graph.TwoDimensional as Graph2D
 import Graphics.Gnuplot.Plot.TwoDimensional (linearScale, )
 
+import qualified Data.Time as Time
+
 import Data.Array (listArray, )
 import Data.Monoid (mappend, )
 
 
-simple2d :: Plot2D.T
+simple2d :: Plot2D.T Double Double
 simple2d =
-   Plot2D.function (linearScale 100 (-10,10::Double)) sin
+   Plot2D.function Graph2D.lines
+      (linearScale 100 (-10,10)) sin
 
-circle2d :: Plot2D.T
+circle2d :: Plot2D.T Double Double
 circle2d =
-   fmap
-      (Graph2D.typ Graph2D.points)
-      (Plot2D.parameterFunction
-         (linearScale 24 (-pi,pi::Double))
-         (\t -> (cos t, sin t)))
+   Plot2D.parameterFunction Graph2D.lines
+      (linearScale 24 (-pi,pi))
+      (\t -> (cos t, sin t))
 
-overlay2d :: Frame.T Graph2D.T
+list2d :: Plot2D.T Int Integer
+list2d =
+   Plot2D.list Graph2D.listPoints [0,1,1,2,3,5,8,13::Integer]
+
+candle2d :: Plot2D.T Time.Day Double
+candle2d =
+   Plot2D.list Graph2D.candleSticks $
+   zip [(Time.fromGregorian 2008 01 01) ..] $
+   flip map (linearScale 32 (0,2*pi)) $
+   \t -> (-sin t, -2*sin t, 2*sin t, sin t)
+
+overlay2d :: Frame.T (Graph2D.T Double Double)
 overlay2d =
    Frame.cons (Opts.size 1 0.4 $ Opts.remove Opt.key $ Opts.deflt) $
-   Plot2D.function (linearScale 100 (-pi,pi::Double)) cos
+   Plot2D.function Graph2D.lines (linearScale 100 (-pi,pi)) cos
    `mappend`
    circle2d
 
-multiplot2d :: MultiPlot.T
-multiplot2d =
-   let opts :: Opts.T graph
-       opts =
-          Opts.remove Opt.key $
-          Opts.deflt
-       (prefix,suffix) =
+mixed2d :: MultiPlot.T
+mixed2d =
+   MultiPlot.simpleFromPartArray $
+   listArray ((0::Int,0::Int), (0,2)) $
+   MultiPlot.partFromPlot circle2d :
+   MultiPlot.partFromFrame
+      (Frame.cons (Opts.xFormat "%m-%d" $ Opts.remove Opt.key $ Opts.deflt) $
+       candle2d) :
+   MultiPlot.partFromPlot list2d :
+   []
+
+{-
+The size settings of overlay2d interfer badly with the other plots,
+because 'unset' does not restore the size to the multiplot settings.
+-}
+size2d :: MultiPlot.T
+size2d =
+   MultiPlot.simpleFromPartArray $
+   listArray ((0::Int,0::Int), (0,2)) $
+   MultiPlot.partFromPlot candle2d :
+   MultiPlot.partFromFrame
+      (Frame.cons (Opts.yLabel "Fibonacci" $ Opts.remove Opt.key $ Opts.deflt)
+       list2d) :
+   MultiPlot.partFromPlot candle2d :
+   []
+
+defltOpts :: Graph.C graph => Opts.T graph
+defltOpts =
+   Opts.remove Opt.key $
+   Opts.deflt
+
+wave3d :: Frame.T (Graph3D.T Double Double Double)
+wave3d =
+   let meshNodes = linearScale 20 (-2,2)
+   in  Frame.cons
+          (Opts.xRange3d (-2.5,2.5) $
+           Opts.yRange3d (-2.5,2.5) $
+           defltOpts) $
+       Plot3D.surface
+          meshNodes meshNodes
+          (\x y -> cos(x*x+y*y))
+
+multiplot :: MultiPlot.T
+multiplot =
+   let (prefix,suffix) =
           splitAt 7 $
           map MultiPlot.partFromFrame $
           map (\k ->
-             Frame.cons (Opts.xRange (-1,1) opts) $
-             Plot2D.parameterFunction
+             Frame.cons (Opts.xRange2d (-1,1) defltOpts) $
+             Plot2D.parameterFunction Graph2D.lines
                 (linearScale 48 (-pi,pi::Double))
                 (\t -> (cos (t + pi/7*fromInteger k), sin (2*t)))) $
           [0..13]
-       meshNodes = linearScale 20 (-2,2::Double)
 {-
        center =
-          MultiPlot.partFromFrame $
-          Frame.empty
+          MultiPlot.partFromFrame Frame.empty
 -}
        center =
-          MultiPlot.partFromFrame $
-          Frame.cons
-             (Opts.xRange (-2.5,2.5) $
-              Opts.yRange (-2.5,2.5) $
-              opts) $
-          (Plot3D.function
-             meshNodes meshNodes
-             (\x y -> cos(x*x+y*y)))
+          MultiPlot.partFromFrame wave3d
    in  MultiPlot.simpleFromPartArray $
        listArray ((0::Int,0::Int), (2,4)) $
        prefix ++ center : suffix
@@ -76,6 +120,11 @@
 main :: IO ()
 main =
    do Plot.plot X11.cons simple2d
+      Plot.plot X11.cons list2d
+      Plot.plot X11.cons candle2d
       Plot.plot X11.cons overlay2d
-      Plot.plot X11.cons multiplot2d
+      Plot.plot X11.cons mixed2d
+      Plot.plot X11.cons size2d
+      Plot.plot X11.cons wave3d
+      Plot.plot X11.cons multiplot
       return ()
diff --git a/src/Graphics/Gnuplot/Advanced.hs b/src/Graphics/Gnuplot/Advanced.hs
--- a/src/Graphics/Gnuplot/Advanced.hs
+++ b/src/Graphics/Gnuplot/Advanced.hs
@@ -101,7 +101,7 @@
    terminal -> gfx -> IO ExitCode
 plot term gfx =
    let body =
-          State.evaluate (0, OptionSet.decons OptionSet.deflt) $
+          State.evaluate (0, OptionSet.initial) $
           Display.runScript $
           Display.toScript gfx
    in  do mapM_ Display.writeData (Display.files body)
diff --git a/src/Graphics/Gnuplot/Frame.hs b/src/Graphics/Gnuplot/Frame.hs
--- a/src/Graphics/Gnuplot/Frame.hs
+++ b/src/Graphics/Gnuplot/Frame.hs
@@ -3,19 +3,20 @@
    cons, simple, empty,
    ) where
 
+import qualified Graphics.Gnuplot.Frame.OptionSet as OptionSet
 import qualified Graphics.Gnuplot.Private.Frame as Frame
 import qualified Graphics.Gnuplot.Private.Plot as Plot
-import qualified Graphics.Gnuplot.Private.FrameOptionSet as Option
 import qualified Graphics.Gnuplot.Private.GraphEmpty as Empty
+import qualified Graphics.Gnuplot.Private.Graph as Graph
 
 import qualified Data.Monoid.State as State
 
 
-cons :: Option.T graph -> Plot.T graph -> Frame.T graph
+cons :: OptionSet.T graph -> Plot.T graph -> Frame.T graph
 cons = Frame.Cons
 
-simple :: Plot.T graph -> Frame.T graph
-simple = cons Option.deflt
+simple :: Graph.C graph => Plot.T graph -> Frame.T graph
+simple = cons OptionSet.deflt
 
 empty :: Frame.T Empty.T
 empty =
diff --git a/src/Graphics/Gnuplot/Frame/OptionSet.hs b/src/Graphics/Gnuplot/Frame/OptionSet.hs
--- a/src/Graphics/Gnuplot/Frame/OptionSet.hs
+++ b/src/Graphics/Gnuplot/Frame/OptionSet.hs
@@ -1,18 +1,23 @@
 module Graphics.Gnuplot.Frame.OptionSet (
    OptionSet.T,
-   OptionSet.deflt,
+   deflt,
 
    OptionSet.add,
    OptionSet.remove,
 
    size,
    title,
-   xRange,
-   yRange,
-   zRange,
+   xRange2d,
+   yRange2d,
+   xRange3d,
+   yRange3d,
+   zRange3d,
    xLabel,
    yLabel,
    zLabel,
+   xFormat,
+   yFormat,
+   zFormat,
 
    view,
    viewMap,
@@ -20,17 +25,25 @@
 
 
 import qualified Graphics.Gnuplot.Graph.ThreeDimensional as Graph3D
+import qualified Graphics.Gnuplot.Graph.TwoDimensional as Graph2D
 
 import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
 import qualified Graphics.Gnuplot.Private.FrameOption as Option
 import qualified Graphics.Gnuplot.Private.Graph as Graph
 
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+
 import Graphics.Gnuplot.Private.FrameOptionSet (T, )
 
 import Graphics.Gnuplot.Utility
    (quote, )
 
 
+deflt :: Graph.C graph => T graph
+deflt = Graph.defltOptions
+
+
 size :: Graph.C graph => Double -> Double -> T graph -> T graph
 size x y =
    OptionSet.add Option.size [show x ++ ", " ++ show y]
@@ -40,18 +53,53 @@
    OptionSet.add Option.title [quote text]
 
 
+{-
 xRange :: Graph.C graph => (Double, Double) -> T graph -> T graph
 xRange = range Option.xRange
 
 yRange :: Graph.C graph => (Double, Double) -> T graph -> T graph
 yRange = range Option.yRange
 
-zRange :: (Double, Double) -> T Graph3D.T -> T Graph3D.T
+zRange :: (Double, Double) -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 zRange = range Option.zRange
+-}
 
-range :: Graph.C graph => Option.T -> (Double, Double) -> T graph -> T graph
+xRange2d ::
+   (Atom.C x, Atom.C y, Tuple.C x) =>
+   (x, x) -> T (Graph2D.T x y) -> T (Graph2D.T x y)
+xRange2d = range Option.xRange
+
+yRange2d ::
+   (Atom.C x, Atom.C y, Tuple.C y) =>
+   (y, y) -> T (Graph2D.T x y) -> T (Graph2D.T x y)
+yRange2d = range Option.yRange
+
+
+xRange3d ::
+   (Atom.C x, Atom.C y, Atom.C z, Tuple.C x) =>
+   (x, x) -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
+xRange3d = range Option.xRange
+
+yRange3d ::
+   (Atom.C x, Atom.C y, Atom.C z, Tuple.C y) =>
+   (y, y) -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
+yRange3d = range Option.yRange
+
+zRange3d ::
+   (Atom.C x, Atom.C y, Atom.C z, Tuple.C z) =>
+   (z, z) -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
+zRange3d = range Option.zRange
+
+
+range ::
+   (Atom.C a, Tuple.C a, Graph.C graph) =>
+   Option.T -> (a, a) -> T graph -> T graph
 range opt (x,y) =
-   OptionSet.add opt ["[" ++ show x ++ ":" ++ show y ++ "]"]
+   let fromSingleton = \[s] -> s
+   in  OptionSet.add opt
+          [showString "[" . fromSingleton (Tuple.text x) .
+           showString ":" . fromSingleton (Tuple.text y) $
+           "]"]
 
 
 xLabel :: Graph.C graph => String -> T graph -> T graph
@@ -60,7 +108,9 @@
 yLabel :: Graph.C graph => String -> T graph -> T graph
 yLabel = label Option.yLabel
 
-zLabel :: String -> T Graph3D.T -> T Graph3D.T
+zLabel ::
+   (Atom.C x, Atom.C y, Atom.C z) =>
+   String -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 zLabel = label Option.zLabel
 
 label :: Graph.C graph => Option.T -> String -> T graph -> T graph
@@ -68,6 +118,22 @@
    OptionSet.add opt [quote x]
 
 
+xFormat :: Graph.C graph => String -> T graph -> T graph
+xFormat = format Option.xFormat
+
+yFormat :: Graph.C graph => String -> T graph -> T graph
+yFormat = format Option.yFormat
+
+zFormat ::
+   (Atom.C x, Atom.C y, Atom.C z) =>
+   String -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
+zFormat = format Option.zFormat
+
+format :: Graph.C graph => Option.T -> String -> T graph -> T graph
+format opt x =
+   OptionSet.add opt [quote x]
+
+
 {- |
 Set parameters of viewing a surface graph.
 See <info:gnuplot/view>
@@ -77,14 +143,14 @@
    Double {- ^ rotateZ -} ->
    Double {- ^ scale -} ->
    Double {- ^ scaleZ -} ->
-   T Graph3D.T -> T Graph3D.T
+   T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 view rotateX rotateZ scale scaleZ =
    OptionSet.add Option.view [show rotateX, show rotateZ, show scale, show scaleZ]
 
 {- |
 Show flat pixel map.
 -}
-viewMap :: T Graph3D.T -> T Graph3D.T
+viewMap :: T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 viewMap =
    OptionSet.add Option.view ["map"]
 
@@ -95,7 +161,7 @@
 yTicks :: Graph.C graph => Double -> Double -> T graph -> T graph
 yTicks = ticks Option.yTicks
 
-zTicks :: Double -> Double -> T Graph3D.T -> T Graph3D.T
+zTicks :: Double -> Double -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 zTicks = ticks Option.zTicks
 
 ticks :: Graph.C graph => Option.T -> Double -> Double -> T graph -> T graph
@@ -104,7 +170,7 @@
 -}
 
 {-
-cornerToColor :: CornersToColor -> T Graph3D.T -> T Graph3D.T
+cornerToColor :: CornersToColor -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 
-type3d :: Plot3dType -> T Graph3D.T -> T Graph3D.T
+type3d :: Plot3dType -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
 -}
diff --git a/src/Graphics/Gnuplot/Graph.hs b/src/Graphics/Gnuplot/Graph.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Graph.hs
@@ -0,0 +1,3 @@
+module Graphics.Gnuplot.Graph (Graph.C) where
+
+import qualified Graphics.Gnuplot.Private.Graph as Graph
diff --git a/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs b/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
--- a/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
+++ b/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
@@ -2,39 +2,16 @@
    T,
    Type,
 
-   defaultType,
-   deflt,
+--   deflt,
 
-   typ,
    lineSpec,
 
-   lines,
-   points,
-   linesPoints,
    impulses,
-   dots,
-   steps,
-   fSteps,
-   hiSteps,
-   errorBars,
-   xErrorBars,
-   yErrorBars,
-   xyErrorBars,
-   errorLines,
-   xErrorLines,
-   yErrorLines,
-   xyErrorLines,
-   boxes,
-   filledCurves,
-   boxErrorBars,
-   boxXYErrorBars,
-   financeBars,
-   candleSticks,
    vectors,
    pm3d,
    ) where
 
 import Graphics.Gnuplot.Private.Graph3D
-import Graphics.Gnuplot.Private.GraphType hiding (T, )
+import Graphics.Gnuplot.Private.Graph3DType hiding (T, )
 
 import Prelude hiding (lines, )
diff --git a/src/Graphics/Gnuplot/Graph/TwoDimensional.hs b/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
--- a/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
+++ b/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
@@ -2,12 +2,30 @@
    T,
    Type,
 
-   defaultType,
-   deflt,
+--   deflt,
 
-   typ,
    lineSpec,
 
+   listLines,
+   listPoints,
+   listLinesPoints,
+   listImpulses,
+   listDots,
+
+   xErrorBarsRelative,
+   yErrorBarsRelative,
+   xyErrorBarsRelative,
+   xErrorBarsAbsolute,
+   yErrorBarsAbsolute,
+   xyErrorBarsAbsolute,
+
+   xErrorLinesRelative,
+   yErrorLinesRelative,
+   xyErrorLinesRelative,
+   xErrorLinesAbsolute,
+   yErrorLinesAbsolute,
+   xyErrorLinesAbsolute,
+
    lines,
    points,
    linesPoints,
@@ -17,24 +35,19 @@
    fSteps,
    hiSteps,
    errorBars,
-   xErrorBars,
-   yErrorBars,
-   xyErrorBars,
    errorLines,
-   xErrorLines,
-   yErrorLines,
-   xyErrorLines,
    boxes,
    filledCurves,
+{-
    boxErrorBars,
    boxXYErrorBars,
+-}
    financeBars,
    candleSticks,
    vectors,
-   -- pm3d,
    ) where
 
 import Graphics.Gnuplot.Private.Graph2D
-import Graphics.Gnuplot.Private.GraphType hiding (T, )
+import Graphics.Gnuplot.Private.Graph2DType hiding (T, )
 
 import Prelude hiding (lines, )
diff --git a/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs b/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
--- a/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
+++ b/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
@@ -1,13 +1,23 @@
 module Graphics.Gnuplot.Plot.ThreeDimensional (
+   T,
+   cloud,
+--   function,
+   mesh,
+   surface,
+
    linearScale,
-   module Graphics.Gnuplot.Plot.ThreeDimensional,
+   functionToGraph,
    ) where
 
+import qualified Graphics.Gnuplot.Private.Graph3DType as Type
 import qualified Graphics.Gnuplot.Private.Graph3D as Graph
 import qualified Graphics.Gnuplot.Private.Plot    as Plot
+-- import qualified Graphics.Gnuplot.Value.ColumnSet as Col
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+import qualified Graphics.Gnuplot.Value.Atom  as Atom
 
 import Graphics.Gnuplot.Utility
-   (showTriplet, linearScale, )
+   (functionToGraph, linearScale, assembleCells, )
 
 import Data.List.HT (outerProduct, )
 
@@ -15,21 +25,43 @@
 {- |
 Plots can be assembled using 'mappend' or 'mconcat'.
 -}
-type T = Plot.T Graph.T
+type T x y z = Plot.T (Graph.T x y z)
 
 
 -- * computed plots
 
-mesh ::
-   (Show a, Show b, Show c) =>
-   [[(a,b,c)]] -> T
-mesh dat =
+cloud ::
+   (Atom.C x, Atom.C y, Atom.C z,
+    Tuple.C a) =>
+   Type.T x y z a -> [a] -> T x y z
+cloud typ ps =
    Plot.withUniqueFile
-      (unlines (map (unlines . map showTriplet) dat))
-      [Graph.deflt (Graph.Dim3 1 2 3)]
+      (assembleCells (map Tuple.text ps))
+      [Graph.deflt typ [1 .. Type.tupleSize typ]]
 
+{-
 function ::
-   (Show a, Show b, Show c) =>
-   [b] -> [c] -> (b -> c -> a) -> T
+   (Atom.C x, Atom.C y, Atom.C z) =>
+   Type.T (x,y,z) -> [x] -> [y] -> (x -> y -> z) -> T
 function xArgs yArgs f =
+   cloud (liftM2 (\x y -> (x, y, f x y)) xArgs yArgs)
+-}
+
+
+mesh ::
+   (Atom.C x, Atom.C y, Atom.C z,
+    Tuple.C x, Tuple.C y, Tuple.C z) =>
+   [[(x,y,z)]] -> T x y z
+mesh pss =
+   let typ :: [[a]] -> Type.T x y z a -> Type.T x y z a
+       typ _ = id
+   in  Plot.withUniqueFile
+          (assembleCells (concat (map (\ps -> map Tuple.text ps ++ [[]]) pss)))
+          [Graph.deflt (typ pss Type.pm3d) (1:2:3:[])]
+
+surface ::
+   (Atom.C x, Atom.C y, Atom.C z,
+    Tuple.C x, Tuple.C y, Tuple.C z) =>
+   [x] -> [y] -> (x -> y -> z) -> T x y z
+surface xArgs yArgs f =
    mesh (outerProduct (\x y -> (x, y, f x y)) xArgs yArgs)
diff --git a/src/Graphics/Gnuplot/Plot/TwoDimensional.hs b/src/Graphics/Gnuplot/Plot/TwoDimensional.hs
--- a/src/Graphics/Gnuplot/Plot/TwoDimensional.hs
+++ b/src/Graphics/Gnuplot/Plot/TwoDimensional.hs
@@ -1,73 +1,112 @@
 -- shall this also export Graph.Type, set plotType and so on?
 module Graphics.Gnuplot.Plot.TwoDimensional (
+   T,
+
+   list,
+   function,
+   functions,
+   parameterFunction,
+
+   listFromFile,
+   pathFromFile,
+
    linearScale,
-   module Graphics.Gnuplot.Plot.TwoDimensional,
+   functionToGraph,
    ) where
 
+import qualified Graphics.Gnuplot.Private.Graph2DType as Type
 import qualified Graphics.Gnuplot.Private.Graph2D as Graph
 import qualified Graphics.Gnuplot.Private.Plot    as Plot
+import qualified Graphics.Gnuplot.Value.ColumnSet as Col
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+import qualified Graphics.Gnuplot.Value.Atom  as Atom
 
 import Graphics.Gnuplot.Utility
-   (functionToGraph, commaConcat, linearScale, )
+   (functionToGraph, linearScale, assembleCells, )
 
 import qualified Data.List.Match as Match
+import qualified Data.List.HT as ListHT
 
 
 {- |
 Plots can be assembled using 'mappend' or 'mconcat'.
 -}
-type T = Plot.T Graph.T
+type T x y = Plot.T (Graph.T x y)
 
 
 -- * computed plots
 
 {- |
-> list (take 30 (let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) in fibs))
+> list Type.listLines (take 30 (let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) in fibs))
+> list Type.lines (take 30 (let fibs0 = 0 : fibs1; fibs1 = 1 : zipWith (+) fibs0 fibs1 in zip fibs0 fibs1))
 -}
-list :: Show a => [a] -> T
-list dat =
+list ::
+   (Atom.C x, Atom.C y, Tuple.C a) =>
+   Type.T x y a -> [a] -> T x y
+list typ ps =
    Plot.withUniqueFile
-      (unlines (map show dat))
-      ([Graph.deflt (Graph.Dim1 1)])
+      (assembleCells (map Tuple.text ps))
+      [Graph.deflt typ [1 .. Type.tupleSize typ]]
 
 {- |
-> function (linearScale 1000 (-10,10)) sin
+> function Type.line (linearScale 1000 (-10,10)) sin
 -}
-function :: Show a => [a] -> (a -> a) -> T
-function args f =
-   path (functionToGraph args f)
+function ::
+   (Atom.C x, Atom.C y,
+    Tuple.C a, Tuple.C b) =>
+   Type.T x y (a,b) -> [a] -> (a -> b) -> T x y
+function typ args f =
+   list typ (functionToGraph args f)
 
 {- |
-> functions (linearScale 1000 (-10,10)) [sin, cos]
+> functions Type.line (linearScale 1000 (-10,10)) [sin, cos]
 -}
-functions :: Show a => [a] -> [a -> a] -> T
-functions args fs =
+functions ::
+   (Atom.C x, Atom.C y,
+    Tuple.C a, Tuple.C b) =>
+   Type.T x y (a,b) -> [a] -> [a -> b] -> T x y
+functions typ args fs =
    let dat = map (\x -> (x, map ($ x) fs)) args
+       typA :: Type.T x y (a,b) -> Type.T x y a
+       typA = undefined
+       typB :: Type.T x y (a,b) -> Type.T x y b
+       typB = undefined
+       na = Type.tupleSize (typA typ)
    in  Plot.withUniqueFile
-          (unlines (map (commaConcat . map show . uncurry (:)) dat))
+          (assembleCells
+             (map (\(a,b) -> Tuple.text a ++ concatMap Tuple.text b) dat))
           (Match.take fs $
-           map (Graph.deflt . Graph.Dim2 1) [2..])
+           map (\ns -> Graph.deflt typ ([1..na] ++ ns)) $
+           ListHT.sliceVertical (Type.tupleSize (typB typ)) [(na+1)..])
 
-path :: Show a => [(a,a)] -> T
-path dat =
-   Plot.withUniqueFile
-      (unlines (map (\(x,y) -> show x ++ ", " ++ show y) dat))
-      ([Graph.deflt (Graph.Dim2 1 2)])
 
 {- |
-> parameterFunction (linearScale 1000 (0,2*pi)) (\t -> (sin (2*t), cos t))
+> parameterFunction Type.line (linearScale 1000 (0,2*pi)) (\t -> (sin (2*t), cos t))
 -}
-parameterFunction :: Show a => [a] -> (a -> (a,a)) -> T
-parameterFunction args f = path (map f args)
+parameterFunction ::
+   (Atom.C x, Atom.C y,
+    Tuple.C a) =>
+   Type.T x y a -> [t] -> (t -> a) -> T x y
+parameterFunction typ args f = list typ (map f args)
 
 
 
 -- * plot stored data
 
-listFromFile :: FilePath -> Int -> T
-listFromFile filename column =
-   Plot.fromGraphs filename [Graph.deflt (Graph.Dim1 column)]
+fromFile ::
+   (Atom.C x, Atom.C y) =>
+   Type.T x y a -> FilePath -> Col.T a -> T x y
+fromFile typ filename (Col.Cons cs) =
+   Plot.fromGraphs filename [Graph.deflt typ cs]
 
-pathFromFile :: FilePath -> Int -> Int -> T
-pathFromFile filename columnX columnY =
-   Plot.fromGraphs filename [Graph.deflt (Graph.Dim2 columnX columnY)]
+listFromFile ::
+   (Atom.C i, Atom.C y) =>
+   Type.T i y y -> FilePath -> Int -> T i y
+listFromFile typ filename column =
+   fromFile typ filename (Col.atom column)
+
+pathFromFile ::
+   (Atom.C x, Atom.C y) =>
+   Type.T x y (x,y) -> FilePath -> Int -> Int -> T x y
+pathFromFile typ filename columnX columnY =
+   fromFile typ filename (Col.pair (Col.atom columnX) (Col.atom columnY))
diff --git a/src/Graphics/Gnuplot/Private/Frame.hs b/src/Graphics/Gnuplot/Private/Frame.hs
--- a/src/Graphics/Gnuplot/Private/Frame.hs
+++ b/src/Graphics/Gnuplot/Private/Frame.hs
@@ -20,9 +20,9 @@
    toScript frame =
       (Display.Script $
          State.Cons $ \(n, opts0) ->
-            let opts1 = option frame
+            let opts1 = OptionSet.decons $ option frame
             in  (Display.Body [] $
-                 OptionSet.diffToString (OptionSet.Cons opts0) opts1,
-                 (n, OptionSet.decons opts1)))
+                 OptionSet.diffToString opts0 opts1,
+                 (n, opts1)))
       `mappend`
-      (Display.toScript $ plot frame)
+      (Plot.toScript $ plot frame)
diff --git a/src/Graphics/Gnuplot/Private/FrameOption.hs b/src/Graphics/Gnuplot/Private/FrameOption.hs
--- a/src/Graphics/Gnuplot/Private/FrameOption.hs
+++ b/src/Graphics/Gnuplot/Private/FrameOption.hs
@@ -25,3 +25,13 @@
 xTicks :: T; xTicks = Cons "xtics"
 yTicks :: T; yTicks = Cons "ytics"
 zTicks :: T; zTicks = Cons "ztics"
+
+xData  :: T; xData  = Cons "xdata"
+yData  :: T; yData  = Cons "ydata"
+zData  :: T; zData  = Cons "zdata"
+
+xFormat :: T; xFormat = Cons "format x"
+yFormat :: T; yFormat = Cons "format y"
+zFormat :: T; zFormat = Cons "format z"
+
+timeFmt :: T; timeFmt = Cons "timefmt"
diff --git a/src/Graphics/Gnuplot/Private/FrameOptionSet.hs b/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
--- a/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
+++ b/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
@@ -11,6 +11,7 @@
 module Graphics.Gnuplot.Private.FrameOptionSet where
 
 import qualified Graphics.Gnuplot.Private.FrameOption as Option
+-- import Graphics.Gnuplot.Utility (quote, )
 
 import qualified Data.Map as Map
 
@@ -18,17 +19,19 @@
 import Data.Maybe (mapMaybe, )
 
 
+type Plain = Map.Map Option.T [String]
+
 newtype T graph =
-   Cons {decons :: Map.Map Option.T [String]}
+   Cons {decons :: Plain}
 
+
 {- |
 The default options contain what we expect as default value in gnuplot.
-We need an entry for every option
-that cannot be reset by @unset@.
+We need an entry for every option that cannot be reset by @unset@.
 -}
-deflt :: T graph
+deflt :: Plain
 deflt =
-   Cons $ Map.fromList $
+   Map.fromList $
    (Option.key, []) :
    (Option.border, []) :
    (Option.xLabel, []) :
@@ -40,8 +43,21 @@
    (Option.xTicks, []) :
    (Option.yTicks, []) :
    (Option.zTicks, []) :
+   (Option.xFormat, []) :
+   (Option.yFormat, []) :
+   (Option.zFormat, []) :
+--   (Option.timeFmt, [quote "%s"]) :
    []
 
+initial :: Plain
+initial =
+   flip Map.union deflt $
+   Map.fromList $
+   (Option.xData, []) :
+   (Option.yData, []) :
+   (Option.zData, []) :
+--   (Option.timeFmt, []) :
+   []
 
 {- |
 Add an option with arguments as plain strings.
@@ -64,14 +80,14 @@
 Convert the difference between the first and the second option set
 into a sequence of 'set' and 'unset' commands.
 -}
-diffToString :: T graph -> T graph -> [String]
-diffToString (Cons m0) (Cons m1) =
+diffToString :: Plain -> Plain -> [String]
+diffToString m0 m1 =
    mapMaybe
       (\(Option.Cons opt, (old,new)) ->
          toMaybe (old/=new) $
          maybe
             ("unset " ++ opt)
-            (\args -> "set " ++ opt ++ " " ++ unwords args)
+            (\args -> "set " ++ opt ++ concatMap (' ':) args)
             new) $
    Map.toList $
    Map.unionWith
diff --git a/src/Graphics/Gnuplot/Private/Graph.hs b/src/Graphics/Gnuplot/Private/Graph.hs
--- a/src/Graphics/Gnuplot/Private/Graph.hs
+++ b/src/Graphics/Gnuplot/Private/Graph.hs
@@ -1,5 +1,8 @@
 module Graphics.Gnuplot.Private.Graph where
 
+import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
+
 class C graph where
    command :: graph -> String
    toString :: graph -> String
+   defltOptions :: OptionSet.T graph
diff --git a/src/Graphics/Gnuplot/Private/Graph2D.hs b/src/Graphics/Gnuplot/Private/Graph2D.hs
--- a/src/Graphics/Gnuplot/Private/Graph2D.hs
+++ b/src/Graphics/Gnuplot/Private/Graph2D.hs
@@ -1,53 +1,79 @@
 module Graphics.Gnuplot.Private.Graph2D where
 
+import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
+import qualified Graphics.Gnuplot.Private.FrameOption as Option
 import qualified Graphics.Gnuplot.Private.LineSpecification as LineSpec
-import qualified Graphics.Gnuplot.Private.GraphType as GraphType
+import qualified Graphics.Gnuplot.Private.Graph2DType as GraphType
 import qualified Graphics.Gnuplot.Private.Graph as Graph
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+import qualified Data.Map as Map
+import qualified Data.List as List
 
 import Prelude hiding (lines, )
 
 
-data T =
+data T x y =
    Cons {
       column_   :: Column,
       type_     :: Type,
       lineSpec_ :: LineSpec.T
    }
 
-data Column =
-     Dim1 {columnX :: Int}
-   | Dim2 {columnX, columnY :: Int}
-
+type Column = [Int]
 
-type Type = GraphType.T
+type Type = String
 
 
 columnToString :: Column -> String
-columnToString c =
-   case c of
-      Dim1 x -> show x
-      Dim2 x y -> show x ++ ":" ++ show y
+columnToString =
+   concat . List.intersperse ":" . map show
 
-toString :: T -> String
+toString :: T x y -> String
 toString (Cons c t l) =
    "using " ++ columnToString c ++
-   " with " ++ GraphType.toString t ++
+   " with " ++ t ++
    " " ++ LineSpec.toString l
 
-instance Graph.C T where
-   command _ = "plot"
-   toString = toString
 
+type AxisOption x y a =
+   OptionSet.T (T x y) -> (Atom.OptionSet, a)
 
-defaultType :: Type
-defaultType = GraphType.lines
+defltOptions :: (Atom.C x, Atom.C y) => OptionSet.T (T x y)
+defltOptions =
+   let optX :: Atom.C x => AxisOption x y x
+       optX _ = Atom.options
+       optY :: Atom.C y => AxisOption x y y
+       optY _ = Atom.options
+       mk :: Option.T -> Option.T ->
+             (Atom.OptionSet, a) -> [(Option.T, [String])]
+       mk optData optFormat op =
+          let opts = fst op
+          in  (optData, Atom.optData opts) :
+              (optFormat, Atom.optFormat opts) :
+              Atom.optOthers opts
+       result =
+          OptionSet.Cons $
+          flip Map.union OptionSet.deflt $
+          Map.fromList $
+          mk Option.xData Option.xFormat (optX result) ++
+          mk Option.yData Option.yFormat (optY result) ++
+          (Option.zData, []) :
+          (Option.zFormat, []) :
+          []
+   in  result
 
-deflt :: Column -> T
-deflt c = Cons c defaultType LineSpec.deflt
 
+instance (Atom.C x, Atom.C y) => Graph.C (T x y) where
+   command _ = "plot"
+   toString = toString
+   defltOptions = defltOptions
 
-typ :: Type -> T -> T
+
+deflt :: GraphType.T x y a -> Column -> T x y
+deflt t c = Cons c (GraphType.toString t) LineSpec.deflt
+
+typ :: Type -> T x y -> T x y
 typ t gr = gr{type_ = t}
 
-lineSpec :: LineSpec.T -> T -> T
+lineSpec :: LineSpec.T -> T x y -> T x y
 lineSpec ls gr = gr{lineSpec_ = ls}
diff --git a/src/Graphics/Gnuplot/Private/Graph2DType.hs b/src/Graphics/Gnuplot/Private/Graph2DType.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Private/Graph2DType.hs
@@ -0,0 +1,104 @@
+module Graphics.Gnuplot.Private.Graph2DType where
+
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+import Prelude hiding (lines, )
+
+
+newtype T x y a = Cons String
+
+tupleSize :: (Tuple.C a) => T x y a -> Int
+tupleSize =
+   let size :: (Tuple.C a) => T x y a -> (Int, a)
+       size _ = Tuple.number
+   in  fst . size
+
+
+{-
+See info:/gnuplot/set_style_rectangle
+-}
+
+listLines       :: (Atom.C y) => T Int y y
+listPoints      :: (Atom.C y) => T Int y y
+listLinesPoints :: (Atom.C y) => T Int y y
+listImpulses    :: (Atom.C y) => T Int y y
+listDots        :: (Atom.C y) => T Int y y
+
+xErrorBarsRelative   :: (Atom.C x, Atom.C y) => T x y ((x,y),x)
+yErrorBarsRelative   :: (Atom.C x, Atom.C y) => T x y ((x,y),y)
+xyErrorBarsRelative  :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,y))
+xErrorBarsAbsolute   :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,x))
+yErrorBarsAbsolute   :: (Atom.C x, Atom.C y) => T x y ((x,y),(y,y))
+xyErrorBarsAbsolute  :: (Atom.C x, Atom.C y) => T x y ((x,y),((x,x),(y,y)))
+
+xErrorLinesRelative  :: (Atom.C x, Atom.C y) => T x y ((x,y),x)
+yErrorLinesRelative  :: (Atom.C x, Atom.C y) => T x y ((x,y),y)
+xyErrorLinesRelative :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,y))
+xErrorLinesAbsolute  :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,x))
+yErrorLinesAbsolute  :: (Atom.C x, Atom.C y) => T x y ((x,y),(y,y))
+xyErrorLinesAbsolute :: (Atom.C x, Atom.C y) => T x y ((x,y),((x,x),(y,y)))
+
+lines          :: (Atom.C x, Atom.C y) => T x y (x,y)
+points         :: (Atom.C x, Atom.C y) => T x y (x,y)
+linesPoints    :: (Atom.C x, Atom.C y) => T x y (x,y)
+impulses       :: (Atom.C x, Atom.C y) => T x y (x,y)
+dots           :: (Atom.C x, Atom.C y) => T x y (x,y)
+steps          :: (Atom.C x, Atom.C y) => T x y (x,y)
+fSteps         :: (Atom.C x, Atom.C y) => T x y (x,y)
+hiSteps        :: (Atom.C x, Atom.C y) => T x y (x,y)
+errorBars      :: (Atom.C x, Atom.C y) => T x y (x,y)
+errorLines     :: (Atom.C x, Atom.C y) => T x y (x,y)
+boxes          :: (Atom.C x, Atom.C y) => T x y (x,y)
+filledCurves   :: (Atom.C x, Atom.C y) => T x y (x,y)
+{-
+boxErrorBars   :: (Atom.C x, Atom.C y) => T x y (x,y)
+boxXYErrorBars :: (Atom.C x, Atom.C y) => T x y (x,y)
+-}
+financeBars    :: (Atom.C x, Atom.C y) => T x y (x,(y,y,y,y))
+candleSticks   :: (Atom.C x, Atom.C y) => T x y (x,(y,y,y,y))
+vectors        :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,y))
+
+
+listLines       = Cons "lines"
+listPoints      = Cons "points"
+listLinesPoints = Cons "linespoints"
+listImpulses    = Cons "impulses"
+listDots        = Cons "dots"
+
+xErrorBarsRelative   = Cons "xerrorbars"
+yErrorBarsRelative   = Cons "yerrorbars"
+xyErrorBarsRelative  = Cons "xyerrorbars"
+xErrorBarsAbsolute   = Cons "xerrorbars"
+yErrorBarsAbsolute   = Cons "yerrorbars"
+xyErrorBarsAbsolute  = Cons "xyerrorbars"
+
+xErrorLinesRelative  = Cons "xerrorlines"
+yErrorLinesRelative  = Cons "yerrorlines"
+xyErrorLinesRelative = Cons "xyerrorlines"
+xErrorLinesAbsolute  = Cons "xerrorlines"
+yErrorLinesAbsolute  = Cons "yerrorlines"
+xyErrorLinesAbsolute = Cons "xyerrorlines"
+
+lines          = Cons "lines"
+points         = Cons "points"
+linesPoints    = Cons "linespoints"
+impulses       = Cons "impulses"
+dots           = Cons "dots"
+steps          = Cons "steps"
+fSteps         = Cons "fsteps"
+hiSteps        = Cons "histeps"
+errorBars      = Cons "errorbars"
+errorLines     = Cons "errorlines"
+boxes          = Cons "boxes"
+filledCurves   = Cons "filledcurves"
+{-
+boxErrorBars   = Cons "boxerrorbars"
+boxXYErrorBars = Cons "boxxyerrorbars"
+-}
+financeBars    = Cons "financebars"
+candleSticks   = Cons "candlesticks"
+vectors        = Cons "vectors"
+
+
+toString :: T x y a -> String
+toString (Cons t) = t
diff --git a/src/Graphics/Gnuplot/Private/Graph3D.hs b/src/Graphics/Gnuplot/Private/Graph3D.hs
--- a/src/Graphics/Gnuplot/Private/Graph3D.hs
+++ b/src/Graphics/Gnuplot/Private/Graph3D.hs
@@ -1,53 +1,75 @@
 module Graphics.Gnuplot.Private.Graph3D where
 
+import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
+import qualified Graphics.Gnuplot.Private.FrameOption as Option
 import qualified Graphics.Gnuplot.Private.LineSpecification as LineSpec
-import qualified Graphics.Gnuplot.Private.GraphType as GraphType
+import qualified Graphics.Gnuplot.Private.Graph3DType as GraphType
 import qualified Graphics.Gnuplot.Private.Graph as Graph
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+import qualified Data.Map as Map
 
+import Graphics.Gnuplot.Private.Graph2D (Column, columnToString, )
+
 import Prelude hiding (lines, )
 
 
-data T =
+data T x y z =
    Cons {
       column_   :: Column,
       type_     :: Type,
       lineSpec_ :: LineSpec.T
    }
 
-data Column =
-     Dim3 {columnX, columnY, columnZ :: Int}
-   | Dim4 {columnX, columnY, columnZ, columnC :: Int}
-
-
-type Type = GraphType.T
+type Type = String
 
 
-columnToString :: Column -> String
-columnToString col =
-   case col of
-      Dim3 x y z -> show x ++ ":" ++ show y ++ ":" ++ show z
-      Dim4 x y z c -> show x ++ ":" ++ show y ++ ":" ++ show z ++ ":" ++ show c
-
-toString :: T -> String
+toString :: T x y z -> String
 toString (Cons c t l) =
    "using " ++ columnToString c ++
-   " with " ++ GraphType.toString t ++
+   " with " ++ t ++
    " " ++ LineSpec.toString l
 
-instance Graph.C T where
-   command _ = "splot"
-   toString = toString
 
+type AxisOption x y z a =
+   OptionSet.T (T x y z) -> (Atom.OptionSet, a)
 
-defaultType :: Type
-defaultType = GraphType.pm3d
+defltOptions :: (Atom.C x, Atom.C y, Atom.C z) => OptionSet.T (T x y z)
+defltOptions =
+   let optX :: Atom.C x => AxisOption x y z x
+       optX _ = Atom.options
+       optY :: Atom.C y => AxisOption x y z y
+       optY _ = Atom.options
+       optZ :: Atom.C z => AxisOption x y z z
+       optZ _ = Atom.options
+       mk :: Option.T -> Option.T ->
+             (Atom.OptionSet, a) -> [(Option.T, [String])]
+       mk optData optFormat op =
+          let opts = fst op
+          in  (optData, Atom.optData opts) :
+              (optFormat, Atom.optFormat opts) :
+              Atom.optOthers opts
+       result =
+          OptionSet.Cons $
+          flip Map.union OptionSet.deflt $
+          Map.fromList $
+          mk Option.xData Option.xFormat (optX result) ++
+          mk Option.yData Option.yFormat (optY result) ++
+          mk Option.yData Option.yFormat (optZ result) ++
+          []
+   in  result
 
-deflt :: Column -> T
-deflt c = Cons c defaultType LineSpec.deflt
 
+instance (Atom.C x, Atom.C y, Atom.C z) => Graph.C (T x y z) where
+   command _ = "splot"
+   toString = toString
+   defltOptions = defltOptions
 
-typ :: Type -> T -> T
+
+deflt :: GraphType.T x y z a -> Column -> T x y z
+deflt t c = Cons c (GraphType.toString t) LineSpec.deflt
+
+typ :: Type -> T x y z -> T x y z
 typ t gr = gr{type_ = t}
 
-lineSpec :: LineSpec.T -> T -> T
+lineSpec :: LineSpec.T -> T x y z -> T x y z
 lineSpec ls gr = gr{lineSpec_ = ls}
diff --git a/src/Graphics/Gnuplot/Private/Graph3DType.hs b/src/Graphics/Gnuplot/Private/Graph3DType.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Private/Graph3DType.hs
@@ -0,0 +1,32 @@
+module Graphics.Gnuplot.Private.Graph3DType where
+
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+
+import Prelude hiding (lines, )
+
+
+newtype T x y z a = Cons String
+
+tupleSize :: (Tuple.C a) => T x y z a -> Int
+tupleSize =
+   let size :: (Tuple.C a) => T x y z a -> (Int, a)
+       size _ = Tuple.number
+   in  fst . size
+
+
+{-
+See info:/gnuplot/set_style_rectangle
+-}
+
+impulses       :: (Atom.C x, Atom.C y, Atom.C z) => T x y z (x,y,z)
+vectors        :: (Atom.C x, Atom.C y, Atom.C z) => T x y z ((x,y,z), (x,y,z))
+pm3d           :: (Atom.C x, Atom.C y, Atom.C z) => T x y z (x,y,z)
+
+impulses       = Cons "impulses"
+vectors        = Cons "vectors"
+pm3d           = Cons "pm3d"
+
+
+toString :: T x y z a -> String
+toString (Cons t) = t
diff --git a/src/Graphics/Gnuplot/Private/GraphEmpty.hs b/src/Graphics/Gnuplot/Private/GraphEmpty.hs
--- a/src/Graphics/Gnuplot/Private/GraphEmpty.hs
+++ b/src/Graphics/Gnuplot/Private/GraphEmpty.hs
@@ -7,6 +7,7 @@
 module Graphics.Gnuplot.Private.GraphEmpty where
 
 import qualified Graphics.Gnuplot.Private.Graph as Graph
+import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
 
 
 data T = Cons
@@ -15,3 +16,5 @@
 instance Graph.C T where
    command _ = "clear"
    toString = const ""
+   defltOptions =
+      OptionSet.Cons OptionSet.deflt
diff --git a/src/Graphics/Gnuplot/Private/GraphType.hs b/src/Graphics/Gnuplot/Private/GraphType.hs
deleted file mode 100644
--- a/src/Graphics/Gnuplot/Private/GraphType.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-module Graphics.Gnuplot.Private.GraphType where
-
-import Prelude hiding (lines, )
-
-
-newtype T = Cons String
-
-
-lines          :: T
-points         :: T
-linesPoints    :: T
-impulses       :: T
-dots           :: T
-steps          :: T
-fSteps         :: T
-hiSteps        :: T
-errorBars      :: T
-xErrorBars     :: T
-yErrorBars     :: T
-xyErrorBars    :: T
-errorLines     :: T
-xErrorLines    :: T
-yErrorLines    :: T
-xyErrorLines   :: T
-boxes          :: T
-filledCurves   :: T
-boxErrorBars   :: T
-boxXYErrorBars :: T
-financeBars    :: T
-candleSticks   :: T
-vectors        :: T
-pm3d           :: T
-
-lines          = Cons "lines"
-points         = Cons "points"
-linesPoints    = Cons "linespoints"
-impulses       = Cons "impulses"
-dots           = Cons "dots"
-steps          = Cons "steps"
-fSteps         = Cons "fsteps"
-hiSteps        = Cons "histeps"
-errorBars      = Cons "errorbars"
-xErrorBars     = Cons "xerrorbars"
-yErrorBars     = Cons "yerrorbars"
-xyErrorBars    = Cons "xyerrorbars"
-errorLines     = Cons "errorlines"
-xErrorLines    = Cons "xerrorlines"
-yErrorLines    = Cons "yerrorlines"
-xyErrorLines   = Cons "xyerrorlines"
-boxes          = Cons "boxes"
-filledCurves   = Cons "filledcurves"
-boxErrorBars   = Cons "boxerrorbars"
-boxXYErrorBars = Cons "boxxyerrorbars"
-financeBars    = Cons "financebars"
-candleSticks   = Cons "candlesticks"
-vectors        = Cons "vectors"
-pm3d           = Cons "pm3d"
-
-
-toString :: T -> String
-toString (Cons t) = t
diff --git a/src/Graphics/Gnuplot/Private/Plot.hs b/src/Graphics/Gnuplot/Private/Plot.hs
--- a/src/Graphics/Gnuplot/Private/Plot.hs
+++ b/src/Graphics/Gnuplot/Private/Plot.hs
@@ -4,6 +4,7 @@
 import Data.Monoid (Monoid, mempty, mappend, )
 
 import qualified Graphics.Gnuplot.Display as Display
+import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
 import qualified Graphics.Gnuplot.Private.Graph as Graph
 import Graphics.Gnuplot.Utility (quote, commaConcat, )
 
@@ -63,22 +64,42 @@
       fmap (map (\file -> file{graphs_ = map f $ graphs_ file}))
       mp
 
+{- |
+In contrast to the Display.toScript method instantiation
+this function leaves the options,
+and thus can be used to write the Display.toScript instance for Frame.
+-}
+toScript :: Graph.C graph => T graph -> Display.Script
+toScript p@(Cons mp) =
+   Display.Script $ State.Cons $
+      \(n0, opts) ->
+         let (blocks, n1) = State.run mp n0
+             files =
+                mapMaybe
+                   (\blk -> fmap (Display.File (filename_ blk)) (content_ blk))
+                   blocks
+             graphs =
+                concatMap (\blk ->
+                   map (\gr ->
+                           quote (filename_ blk) ++ " " ++
+                           Graph.toString gr) $ graphs_ blk) $
+                   blocks
+         in  (Display.Body files
+                 [plotCmd p undefined ++ " " ++ commaConcat graphs],
+              (n1, opts))
+
 instance Graph.C graph => Display.C (T graph) where
-   toScript p@(Cons mp) =
-      Display.Script $ State.Cons $
-         \(n0, opts) ->
-            let (blocks, n1) = State.run mp n0
-                files =
-                   mapMaybe
-                      (\blk -> fmap (Display.File (filename_ blk)) (content_ blk))
-                      blocks
-                graphs =
-                   concatMap (\blk ->
-                      map (\gr -> quote (filename_ blk) ++ " " ++ Graph.toString gr) $ graphs_ blk) $
-                      blocks
-            in  (Display.Body files
-                    [plotCmd p undefined ++ " " ++ commaConcat graphs],
-                 (n1, opts))
+   toScript plot =
+      (Display.Script $
+         State.Cons $ \(n, opts0) ->
+            let defltOpts :: Graph.C graph => T graph -> OptionSet.T graph
+                defltOpts _ = Graph.defltOptions
+                opts1 = OptionSet.decons (defltOpts plot)
+            in  (Display.Body [] $
+                 OptionSet.diffToString opts0 opts1,
+                 (n, opts1)))
+      `mappend`
+      toScript plot
 
 plotCmd ::
    Graph.C graph =>
diff --git a/src/Graphics/Gnuplot/Simple.hs b/src/Graphics/Gnuplot/Simple.hs
--- a/src/Graphics/Gnuplot/Simple.hs
+++ b/src/Graphics/Gnuplot/Simple.hs
@@ -52,9 +52,12 @@
 import qualified Graphics.Gnuplot.Private.LineSpecification as LineSpec
 import qualified Graphics.Gnuplot.Private.Graph2D as Graph2D
 import qualified Graphics.Gnuplot.Private.Graph3D as Graph3D
-import qualified Graphics.Gnuplot.Private.GraphType as GraphType
+import qualified Graphics.Gnuplot.Private.Graph2DType as GraphType
 import qualified Graphics.Gnuplot.Private.Plot as Plot
 
+import qualified Graphics.Gnuplot.Value.Tuple as Tuple
+import qualified Graphics.Gnuplot.Value.Atom as Atom
+
 {-
 import qualified Graphics.Gnuplot.Terminal.PostScript as PS
 import qualified Graphics.Gnuplot.Terminal.PNG as PNG
@@ -109,8 +112,23 @@
      Ratio Double
    | NoRatio
 
-{- The Int types would be better enumerations
-   but their interpretations depend on the gnuplot output type. :-( -}
+{- |
+Be careful with 'LineTitle'
+which can only be used as part of gnuplot's @plot@ command
+but not as part of @set@.
+That is,
+
+> plotList [LineStyle 0 [LineTitle "foobar"]] [0,5..100::Double]
+
+will leave you with an invalid gnuplot script, whereas
+
+> plotListStyle [] (defaultStyle {lineSpec = CustomStyle [LineTitle "foobar"]}) [0,5..100::Double]
+
+does what you want.
+
+The 'Int' types would be better enumerations
+but their interpretations depend on the gnuplot output type. :-(
+-}
 data LineAttr =
      LineType  Int
    | LineWidth Double
@@ -163,75 +181,109 @@
 
 -- * plot functions
 
+list :: (Tuple.C a) => [a] -> Plot2D.T Double Double
+list = Plot2D.list (GraphType.Cons "lines")
+-- list = Plot2D.list GraphType.listLines
+
 {- |
 > plotList [] (take 30 (let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) in fibs))
 -}
-plotList :: Show a => [Attribute] -> [a] -> IO ()
+plotList ::
+   (Tuple.C a) =>
+   [Attribute] -> [a] -> IO ()
 plotList attrs =
-   plot2d attrs . Plot2D.list
+   plot2d attrs . list
 
-plotListStyle :: Show a => [Attribute] -> PlotStyle -> [a] -> IO ()
+{- |
+> plotListStyle [] (defaultStyle{plotType = CandleSticks}) (Plot2D.functionToGraph (linearScale 32 (0,2*pi::Double)) (\t -> (-sin t, -2*sin t, 2*sin t, sin t)))
+-}
+plotListStyle ::
+   (Tuple.C a) =>
+   [Attribute] -> PlotStyle -> [a] -> IO ()
 plotListStyle attrs style =
-   plot2d attrs . setPlotStyle style . Plot2D.list
+   plot2d attrs . setPlotStyle style . list
 
-plotLists :: Show a => [Attribute] -> [[a]] -> IO ()
+plotLists ::
+   (Tuple.C a) =>
+   [Attribute] -> [[a]] -> IO ()
 plotLists attrs xss =
-   plot2d attrs (mconcat $ map Plot2D.list xss)
+   plot2d attrs (mconcat $ map list xss)
 
-plotListsStyle :: Show a => [Attribute] -> [(PlotStyle, [a])] -> IO ()
+plotListsStyle ::
+   (Tuple.C a) =>
+   [Attribute] -> [(PlotStyle, [a])] -> IO ()
 plotListsStyle attrs =
    plot2d attrs . mconcat .
-   map (\(style,xs) -> setPlotStyle style $ Plot2D.list xs)
+   map (\(style,xs) -> setPlotStyle style $ list xs)
 
 {- |
 > plotFunc [] (linearScale 1000 (-10,10)) sin
 -}
-plotFunc :: Show a => [Attribute] -> [a] -> (a -> a) -> IO ()
+plotFunc ::
+   (Atom.C a, Tuple.C a) =>
+   [Attribute] -> [a] -> (a -> a) -> IO ()
 plotFunc attrs args f =
-   plot2d attrs (Plot2D.function args f)
+   plot2d attrs (Plot2D.function GraphType.lines args f)
 
 {- |
 > plotFuncs [] (linearScale 1000 (-10,10)) [sin, cos]
 -}
-plotFuncs :: Show a => [Attribute] -> [a] -> [a -> a] -> IO ()
+plotFuncs ::
+   (Atom.C a, Tuple.C a) =>
+   [Attribute] -> [a] -> [a -> a] -> IO ()
 plotFuncs attrs args fs =
-   plot2d attrs (Plot2D.functions args fs)
+   plot2d attrs (Plot2D.functions GraphType.lines args fs)
 
-plotPath :: Show a => [Attribute] -> [(a,a)] -> IO ()
+plotPath ::
+   (Tuple.C a) =>
+   [Attribute] -> [(a,a)] -> IO ()
 plotPath attrs =
-   plot2d attrs . Plot2D.path
+   plot2d attrs . list
 
-plotPaths :: Show a => [Attribute] -> [[(a,a)]] -> IO ()
+plotPaths ::
+   (Tuple.C a) =>
+   [Attribute] -> [[(a,a)]] -> IO ()
 plotPaths attrs xss =
-   plot2d attrs (mconcat $ map Plot2D.path xss)
+   plot2d attrs (mconcat $ map list xss)
 
-plotPathStyle :: Show a => [Attribute] -> PlotStyle -> [(a,a)] -> IO ()
+plotPathStyle ::
+   (Tuple.C a) =>
+   [Attribute] -> PlotStyle -> [(a,a)] -> IO ()
 plotPathStyle attrs style =
-   plot2d attrs . setPlotStyle style . Plot2D.path
+   plot2d attrs . setPlotStyle style . list
 
-plotPathsStyle :: Show a => [Attribute] -> [(PlotStyle, [(a,a)])] -> IO ()
+plotPathsStyle ::
+   (Tuple.C a) =>
+   [Attribute] -> [(PlotStyle, [(a,a)])] -> IO ()
 plotPathsStyle attrs =
    plot2d attrs . mconcat .
-   map (\(style,xs) -> setPlotStyle style $ Plot2D.path xs)
+   map (\(style,xs) -> setPlotStyle style $ list xs)
 
 {- |
 > plotParamFunc [] (linearScale 1000 (0,2*pi)) (\t -> (sin (2*t), cos t))
 -}
-plotParamFunc :: Show a => [Attribute] -> [a] -> (a -> (a,a)) -> IO ()
+plotParamFunc ::
+   (Atom.C a, Tuple.C a) =>
+   [Attribute] -> [a] -> (a -> (a,a)) -> IO ()
 plotParamFunc attrs args f =
-   plot2d attrs (Plot2D.parameterFunction args f)
+   plot2d attrs (Plot2D.parameterFunction GraphType.lines args f)
 
 {- |
 > plotParamFuncs [] (linearScale 1000 (0,2*pi)) [\t -> (sin (2*t), cos t), \t -> (cos t, sin (2*t))]
 -}
-plotParamFuncs :: Show a => [Attribute] -> [a] -> [a -> (a,a)] -> IO ()
+plotParamFuncs ::
+   (Atom.C a, Tuple.C a) =>
+   [Attribute] -> [a] -> [a -> (a,a)] -> IO ()
 plotParamFuncs attrs args fs =
-   plot2d attrs (mconcat $ map (Plot2D.parameterFunction args) fs)
+   plot2d attrs (mconcat $
+      map (Plot2D.parameterFunction GraphType.lines args) fs)
 
 
-plotDots :: Show a => [Attribute] -> [(a,a)] -> IO ()
+plotDots ::
+   (Atom.C a, Tuple.C a) =>
+   [Attribute] -> [(a,a)] -> IO ()
 plotDots attrs xs =
-   plot2d attrs (fmap (Graph2D.typ GraphType.dots) $ Plot2D.path xs)
+   plot2d attrs (Plot2D.list GraphType.dots xs)
 
 
 
@@ -256,18 +308,22 @@
 {- |
 > let xs = [-2,-1.8..2::Double] in plotMesh3d [] [] (do x <- xs; return (do y <- xs; return (x,y,cos(x*x+y*y))))
 -}
-plotMesh3d :: (Show a, Show b, Show c) =>
-   [Attribute] -> [Attribute3d] -> [[(a,b,c)]] -> IO ()
+plotMesh3d ::
+   (Atom.C x, Atom.C y, Atom.C z,
+    Tuple.C x, Tuple.C y, Tuple.C z) =>
+   [Attribute] -> [Attribute3d] -> [[(x,y,z)]] -> IO ()
 plotMesh3d attrs pt dat =
    plot3d attrs pt (Plot3D.mesh dat)
 
 {- |
 > let xs = [-2,-1.8..2::Double] in plotFunc3d [] [] xs xs (\x y -> exp(-(x*x+y*y)))
 -}
-plotFunc3d :: (Show a, Show b, Show c) =>
-   [Attribute] -> [Attribute3d] -> [b] -> [c] -> (b -> c -> a) -> IO ()
+plotFunc3d ::
+   (Atom.C x, Atom.C y, Atom.C z,
+    Tuple.C x, Tuple.C y, Tuple.C z) =>
+   [Attribute] -> [Attribute3d] -> [x] -> [y] -> (x -> y -> z) -> IO ()
 plotFunc3d attrs pt xArgs yArgs f =
-   plot3d attrs pt (Plot3D.function xArgs yArgs f)
+   plot3d attrs pt (Plot3D.surface xArgs yArgs f)
 
 
 
@@ -374,33 +430,33 @@
 
 
 
-plotTypeToGraph :: PlotType -> GraphType.T
+plotTypeToGraph :: PlotType -> Graph2D.Type -- GraphType.T
 plotTypeToGraph t =
    case t of
-      Lines          -> GraphType.lines
-      Points         -> GraphType.points
-      LinesPoints    -> GraphType.linesPoints
-      Impulses       -> GraphType.impulses
-      Dots           -> GraphType.dots
-      Steps          -> GraphType.steps
-      FSteps         -> GraphType.fSteps
-      HiSteps        -> GraphType.hiSteps
-      ErrorBars      -> GraphType.errorBars
-      XErrorBars     -> GraphType.xErrorBars
-      YErrorBars     -> GraphType.yErrorBars
-      XYErrorBars    -> GraphType.xyErrorBars
-      ErrorLines     -> GraphType.errorLines
-      XErrorLines    -> GraphType.xErrorLines
-      YErrorLines    -> GraphType.yErrorLines
-      XYErrorLines   -> GraphType.xyErrorLines
-      Boxes          -> GraphType.boxes
-      FilledCurves   -> GraphType.filledCurves
-      BoxErrorBars   -> GraphType.boxErrorBars
-      BoxXYErrorBars -> GraphType.boxXYErrorBars
-      FinanceBars    -> GraphType.financeBars
-      CandleSticks   -> GraphType.candleSticks
-      Vectors        -> GraphType.vectors
-      PM3d           -> GraphType.pm3d
+      Lines          -> "lines"
+      Points         -> "points"
+      LinesPoints    -> "linespoints"
+      Impulses       -> "impulses"
+      Dots           -> "dots"
+      Steps          -> "steps"
+      FSteps         -> "fsteps"
+      HiSteps        -> "histeps"
+      ErrorBars      -> "errorbars"
+      XErrorBars     -> "xerrorbars"
+      YErrorBars     -> "yerrorbars"
+      XYErrorBars    -> "xyerrorbars"
+      ErrorLines     -> "errorlines"
+      XErrorLines    -> "xerrorlines"
+      YErrorLines    -> "yerrorlines"
+      XYErrorLines   -> "xyerrorlines"
+      Boxes          -> "boxes"
+      FilledCurves   -> "filledcurves"
+      BoxErrorBars   -> "boxerrorbars"
+      BoxXYErrorBars -> "boxxyerrorbars"
+      FinanceBars    -> "financebars"
+      CandleSticks   -> "candlesticks"
+      Vectors        -> "vectors"
+      PM3d           -> "pm3d"
 
 
 plot3dTypeToString :: Plot3dType -> String
@@ -423,7 +479,7 @@
 
 
 
-plot2d :: [Attribute] -> Plot2D.T -> IO ()
+plot2d :: [Attribute] -> Plot2D.T x y -> IO ()
 plot2d attrs (Plot.Cons mp) =
    let files = State.evaluate 0 mp
    in  do mapM_ Plot.writeData files
@@ -432,13 +488,13 @@
                 map (\gr -> quote filename ++ " " ++ Graph2D.toString gr) grs) $
              files
 
-setPlotStyle :: PlotStyle -> Plot2D.T -> Plot2D.T
+setPlotStyle :: PlotStyle -> Plot2D.T x y -> Plot2D.T x y
 setPlotStyle ps =
    fmap (Graph2D.typ (plotTypeToGraph $ plotType ps) .
          Graph2D.lineSpec (lineSpecRecord $ lineSpec ps))
 
 
-plot3d :: [Attribute] -> [Attribute3d] -> Plot3D.T -> IO ()
+plot3d :: [Attribute] -> [Attribute3d] -> Plot3D.T x y z -> IO ()
 plot3d attrs pt (Plot.Cons mp) =
    let files = State.evaluate 0 mp
    in  do mapM_ Plot.writeData files
diff --git a/src/Graphics/Gnuplot/Utility.hs b/src/Graphics/Gnuplot/Utility.hs
--- a/src/Graphics/Gnuplot/Utility.hs
+++ b/src/Graphics/Gnuplot/Utility.hs
@@ -3,7 +3,7 @@
 import Data.List (intersperse, )
 
 
-functionToGraph :: [a] -> (a -> a) -> [(a,a)]
+functionToGraph :: [x] -> (x -> y) -> [(x,y)]
 functionToGraph args f = map (\x -> (x, f x)) args
 -- functionToGraph args f = map swap $ attachKey f args
 
@@ -24,3 +24,12 @@
 
 quote :: String -> String
 quote = show
+
+assembleCells :: [[ShowS]] -> String
+assembleCells ps =
+   foldr ($) ""
+      (concatMap
+         (\p ->
+            intersperse (showString ", ") p ++
+            [showString "\n"])
+         ps)
diff --git a/src/Graphics/Gnuplot/Value/Atom.hs b/src/Graphics/Gnuplot/Value/Atom.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Value/Atom.hs
@@ -0,0 +1,54 @@
+{- |
+Provide a class that restricts the range of Haskell types
+to the ones that gnuplot can process.
+-}
+module Graphics.Gnuplot.Value.Atom where
+
+import qualified Graphics.Gnuplot.Private.FrameOption as Option
+import Graphics.Gnuplot.Utility (quote, )
+
+import qualified Data.Time as Time
+import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Int (Int8, Int16, Int32, Int64, )
+import Data.Ratio (Ratio, )
+
+
+data OptionSet =
+   OptionSet {
+      optData :: [String],
+      optFormat :: [String],
+      optOthers :: [(Option.T, [String])]
+   }
+
+class C a where
+   options :: (OptionSet, a)
+   options =
+      (OptionSet [] [{- quote "%g" -}] [],
+       error "gnuplot: dummy atomic value")
+
+instance C Float   where
+instance C Double  where
+instance C Int     where
+instance C Integer where
+instance (Integral a) => C (Ratio a) where
+
+instance C Int8  where
+instance C Int16 where
+instance C Int32 where
+instance C Int64 where
+instance C Word8  where
+instance C Word16 where
+instance C Word32 where
+instance C Word64 where
+
+
+timeOptions :: OptionSet
+timeOptions =
+   OptionSet ["time"] [quote "%d/%m"] [(Option.timeFmt, [quote "%s"])]
+
+instance C Time.Day where
+   options =
+      (timeOptions, error "gnuplot: dummy day value")
+instance C Time.UTCTime where
+   options =
+      (timeOptions, error "gnuplot: dummy utctime value")
diff --git a/src/Graphics/Gnuplot/Value/ColumnSet.hs b/src/Graphics/Gnuplot/Value/ColumnSet.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Value/ColumnSet.hs
@@ -0,0 +1,25 @@
+{- |
+We provide a way to specify a set of columns
+that matches the tuple structure of a certain graph type.
+-}
+module Graphics.Gnuplot.Value.ColumnSet
+   (T(Cons), atom, pair, triple, quadruple,
+   ) where
+
+import qualified Graphics.Gnuplot.Value.Atom  as Atom
+
+
+newtype T a = Cons [Int]
+
+
+atom :: Atom.C a => Int -> T a
+atom i = Cons [i]
+
+pair :: T a -> T b -> T (a,b)
+pair (Cons ai) (Cons bi) = Cons (ai++bi)
+
+triple :: T a -> T b -> T c -> T (a,b,c)
+triple (Cons ai) (Cons bi) (Cons ci) = Cons (ai++bi++ci)
+
+quadruple :: T a -> T b -> T c -> T d -> T (a,b,c,d)
+quadruple (Cons ai) (Cons bi) (Cons ci) (Cons di) = Cons (ai++bi++ci++di)
diff --git a/src/Graphics/Gnuplot/Value/Tuple.hs b/src/Graphics/Gnuplot/Value/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Value/Tuple.hs
@@ -0,0 +1,78 @@
+{- |
+Provide a class that renders multiple Haskell values in a text form
+that is accessible by gnuplot.
+
+Maybe we add a method for the binary interface to gnuplot later.
+-}
+module Graphics.Gnuplot.Value.Tuple
+   (C(text, number),
+   ) where
+
+import System.Locale (defaultTimeLocale, )
+import qualified Data.Time as Time
+
+import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Int (Int8, Int16, Int32, Int64, )
+import Data.Ratio (Ratio, )
+
+
+class C a where
+   text :: a -> [ShowS]
+   {- |
+   The right pair member is a dummy result
+   that is needed only for type inference.
+   Expect that it is undefined
+   -}
+   number :: (Int, a)
+   number = (1, error "gnuplot: dummy tuple value")
+
+
+singleton :: a -> [a]
+singleton = (:[])
+
+
+instance C Float   where text = singleton . shows
+instance C Double  where text = singleton . shows
+instance C Int     where text = singleton . shows
+instance C Integer where text = singleton . shows
+instance (Integral a) => C (Ratio a) where
+   text = singleton . shows . (id :: Double->Double) . realToFrac
+
+instance C Int8  where text = singleton . shows
+instance C Int16 where text = singleton . shows
+instance C Int32 where text = singleton . shows
+instance C Int64 where text = singleton . shows
+instance C Word8  where text = singleton . shows
+instance C Word16 where text = singleton . shows
+instance C Word32 where text = singleton . shows
+instance C Word64 where text = singleton . shows
+
+instance C Time.Day where
+   text d = text $ Time.UTCTime d 0
+instance C Time.UTCTime where
+   text = singleton . showString . Time.formatTime defaultTimeLocale "%s"
+
+
+instance (C a, C b) => C (a,b) where
+   text (a,b) = text a ++ text b
+   number =
+      let (na,a) = number
+          (nb,b) = number
+      in  (na+nb, (a,b))
+
+instance (C a, C b, C c) => C (a,b,c) where
+   text (a,b,c) = text a ++ text b ++ text c
+   number =
+      let (na,a) = number
+          (nb,b) = number
+          (nc,c) = number
+      in  (na+nb+nc, (a,b,c))
+
+instance (C a, C b, C c, C d) => C (a,b,c,d) where
+   text (a,b,c,d) = text a ++ text b ++ text c ++ text d
+   number =
+      let (na,a) = number
+          (nb,b) = number
+          (nc,c) = number
+          (nd,d) = number
+      in  (na+nb+nc+nd, (a,b,c,d))
