{- | 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, columnCount), ColumnCount(ColumnCount), ) where import Data.Time.Format (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, ) import Data.Function (id, ($), (.), ) import Text.Show (Show, ShowS, shows, showString, ) import Prelude (Eq, Ord, Int, Integer, Integral, Float, Double, realToFrac, (+), (++), ) class C a where {- | For values that are also in Atom class, 'text' must generate a singleton list. -} text :: a -> [ShowS] {- | It must hold @ColumnCount (length (text x)) == columnCount@. -} columnCount :: ColumnCount a columnCount = ColumnCount 1 {- | Count numbers of gnuplot data columns for the respective type. Somehow a writer monad with respect to Sum monoid without material monadic result. Cf. ColumnSet module. -} newtype ColumnCount a = ColumnCount Int deriving (Eq, Ord, Show) {- Functor and Applicative instances would be useful for combining column sets, but they are dangerous, because they can bring type and column columnCount out of sync. -} pure :: a -> ColumnCount a pure _ = ColumnCount 0 (<*>) :: ColumnCount (a -> b) -> ColumnCount a -> ColumnCount b ColumnCount n <*> ColumnCount m = ColumnCount (n+m) 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 columnCount = pure (,) <*> columnCount <*> columnCount instance (C a, C b, C c) => C (a,b,c) where text (a,b,c) = text a ++ text b ++ text c columnCount = pure (,,) <*> columnCount <*> columnCount <*> columnCount 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 columnCount = pure (,,,) <*> columnCount <*> columnCount <*> columnCount <*> columnCount