diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,13 @@
+# Version 0.2 (2016-12-15)
+
+  * Renamed function to load CSV file from **load** to **loadCSV**
+  * Added toList function to the series
+  * Implemented CSV Writer
+  * Time Series is instance of Functor
+  * Time Series is instance of Foldable
+  * Implemented mean
+  
+
 # Version 0.1 (2016-12-13)
 
   * Implemented functions
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,12 +1,11 @@
-[![Build Status](https://travis-ci.org/klangner/time-series-lib.svg?branch=master)](https://travis-ci.org/klangner/time-series-lib)
+[![Build Status](https://travis-ci.org/klangner/timeseries.svg?branch=master)](https://travis-ci.org/klangner/timeseries)
 [![Hackage](https://img.shields.io/hackage/v/timeseries.svg)](https://hackage.haskell.org/package/timeseries)
 
 # Welcome to Haskell Time Series library
 
 Implemented functionality:
   * Base operations on time series (get value, slice, max etc.)
-  * Reading from CSV file
-
+  * Reading and writing from CSV file
 
 
 ## Installation
@@ -24,13 +23,13 @@
 and other improvements.
 
 Please report bugs via the
-[github issue tracker](http://github.com/klangner/time-series-lib/issues).
+[github issue tracker](http://github.com/klangner/timeseries/issues).
 
-Master [git repository](http://github.com/klangner/time-series-lib):
+Master [git repository](http://github.com/klangner/timeseries):
 
-* `git clone https://github.com/klangner/time-series-lib.git`
+* `git clone https://github.com/klangner/timeseries.git`
 
 
 # Redistributing
 
-time-series-lib source code is distributed under the BSD3 License.
+timeseries source code is distributed under the BSD3 License.
diff --git a/benchmark/Benchmarks.hs b/benchmark/Benchmarks.hs
--- a/benchmark/Benchmarks.hs
+++ b/benchmark/Benchmarks.hs
@@ -1,10 +1,16 @@
 
 import Criterion.Main
+import Control.DeepSeq
 import Data.Time (UTCTime)
 import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+import Data.Text.Time (parseISODateTime)
 import qualified Data.TimeSeries as TS
 
 
+instance NFData a => NFData (TS.Series a) where
+    rnf xs = rnf (TS.toList xs)
+
+
 seriesSize :: Integer
 seriesSize = 10^6
 
@@ -14,15 +20,19 @@
 lastIndex :: UTCTime
 lastIndex = index (seriesSize - 1)
 
-bigSeries :: TS.Series
+bigSeries :: TS.Series Double
 bigSeries = TS.tsSeries [1..seriesSize] [1..]
 
 
 main :: IO ()
 main = defaultMain
-    [ bgroup "Big series"
+    [ bgroup "Basic operations"
         [ bench "size"  $ nf TS.size bigSeries
         , bench "valueAt"  $ nf (\xs -> TS.valueAt xs lastIndex) bigSeries
         , bench "slice"  $ nf (\xs -> TS.valueAt (TS.slice xs (index 2) lastIndex) (index 1)) bigSeries
+        , bench "max"  $ nf maximum bigSeries
+        , bench "fmap"  $ nf (fmap (+ 2)) bigSeries
         ]
+    , bgroup "IO"
+        [ bench "load CSV" $ nfIO (TS.loadCSV TS.NoHeader parseISODateTime "../testdata/test-100K.csv") ]
     ]
diff --git a/src/Data/TimeSeries.hs b/src/Data/TimeSeries.hs
--- a/src/Data/TimeSeries.hs
+++ b/src/Data/TimeSeries.hs
@@ -1,9 +1,13 @@
 -- | TimeSeries library
 module Data.TimeSeries
     ( module Data.TimeSeries.Series
-    , module Data.TimeSeries.CSVReader
+    , module Data.TimeSeries.Stats
+    , module Data.TimeSeries.IO.CSVReader
+    , module Data.TimeSeries.IO.CSVWriter
     ) where
 
 
 import Data.TimeSeries.Series
-import Data.TimeSeries.CSVReader
+import Data.TimeSeries.Stats
+import Data.TimeSeries.IO.CSVReader
+import Data.TimeSeries.IO.CSVWriter
diff --git a/src/Data/TimeSeries/CSVReader.hs b/src/Data/TimeSeries/CSVReader.hs
deleted file mode 100644
--- a/src/Data/TimeSeries/CSVReader.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.TimeSeries.CSVReader
-    ( load
-    )where
-
-
-import qualified Data.ByteString.Lazy as BS
-import qualified Data.Text as T
-import           Data.Csv
-import qualified Data.Vector as V
-import           Data.Time (UTCTime)
-
-import           Data.TimeSeries.Series ( Series
-                                        , emptySeries
-                                        , series
-                                        )
-
-
--- | Load data from CSV file and create Time Series from it
--- As a first argument provide function to convert date from ByteString to UTCTime
-load :: (T.Text -> UTCTime) -> FilePath -> IO Series
-load ft filePath = do
-    csvData <- BS.readFile filePath
-    case decode HasHeader csvData of
-        Left err -> do
-            _ <- putStrLn err
-            return emptySeries
-
-        Right vs -> do
-            let vs' = V.map (parseLine ft) vs
-            return $ series (V.toList vs')
-
-
-parseLine :: (T.Text -> UTCTime) -> (T.Text, Double) -> (UTCTime, Double)
-parseLine ft (date, value) = (ft date, value)
diff --git a/src/Data/TimeSeries/IO/CSVReader.hs b/src/Data/TimeSeries/IO/CSVReader.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries/IO/CSVReader.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Data.TimeSeries.IO.CSVReader
+    ( HasHeader(..)
+    , loadCSV
+    )where
+
+
+import qualified Data.ByteString.Lazy as BS
+import qualified Data.Text as T
+import qualified Data.Csv as CSV
+import qualified Data.Vector as V
+import           Data.Time (UTCTime)
+
+import           Data.TimeSeries.Series ( Series
+                                        , emptySeries
+                                        , series
+                                        )
+
+data HasHeader = HasHeader | NoHeader
+
+-- | Load data from CSV file and create Time Series from it
+-- As a first argument provide function to convert date from ByteString to UTCTime
+loadCSV :: HasHeader -> (T.Text -> UTCTime) -> FilePath -> IO (Series Double)
+loadCSV hasHeader ft filePath = do
+    csvData <- BS.readFile filePath
+    case CSV.decode (toCSVHeader hasHeader) csvData of
+        Left err -> do
+            _ <- putStrLn err
+            return emptySeries
+
+        Right vs -> do
+            let vs' = V.map (parseLine ft) vs
+            return $ series (V.toList vs')
+
+
+toCSVHeader :: HasHeader -> CSV.HasHeader
+toCSVHeader HasHeader = CSV.HasHeader
+toCSVHeader _ = CSV.NoHeader
+
+parseLine :: (T.Text -> UTCTime) -> (T.Text, Double) -> (UTCTime, Double)
+parseLine ft (date, value) = (ft date, value)
diff --git a/src/Data/TimeSeries/IO/CSVWriter.hs b/src/Data/TimeSeries/IO/CSVWriter.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries/IO/CSVWriter.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Data.TimeSeries.IO.CSVWriter( saveCSV ) where
+
+
+import Prelude hiding (writeFile)
+import Data.Csv
+import Data.ByteString.Lazy (writeFile)
+import Data.Text.Time ( formatISODateTime )
+
+import Data.TimeSeries.Series ( Series
+                              , toList )
+
+
+-- | Load data from CSV file and create Time Series from it
+-- As a first argument provide function to convert date from ByteString to UTCTime
+saveCSV :: Series Double -> FilePath -> IO ()
+saveCSV ts filePath = do
+    let rs = map (\(x, y) -> (formatISODateTime x, y)) (toList ts)
+    let rs' = encode rs
+    writeFile filePath rs'
diff --git a/src/Data/TimeSeries/Series.hs b/src/Data/TimeSeries/Series.hs
--- a/src/Data/TimeSeries/Series.hs
+++ b/src/Data/TimeSeries/Series.hs
@@ -11,15 +11,14 @@
 module Data.TimeSeries.Series
     ( DataPoint
     , Series
-    , Value
     , emptySeries
-    , max
-    , min
     , series
     , size
     , slice
+    , toList
     , tsSeries
     , valueAt
+    , values
     ) where
 
 import Prelude hiding (max, min)
@@ -27,21 +26,36 @@
 import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
 
 
-type Value = Double
-data DataPoint = DP !UTCTime !Value
+-- | Data points is single index value od time series
+data DataPoint a = DP !UTCTime a
                  deriving (Show, Eq)
 
-data Series = Series [DataPoint]
+instance Functor DataPoint where
+    fmap f (DP x y) = DP x (f y)
+
+instance Foldable DataPoint where
+    foldMap f (DP _ y) = f y
+
+-- | Data structure for holding Series.
+-- Implementation should be hidden so it can be changed in the future
+data Series a = Series [DataPoint a]
     deriving (Show, Eq)
 
+instance Functor Series where
+    fmap f (Series xs) = Series (map (fmap f) xs)
 
+instance Foldable Series where
+    foldMap f (Series xs) = foldMap (foldMap f) xs
+    length = size
+
+
 -- | Create empty series
-emptySeries :: Series
+emptySeries :: Series a
 emptySeries = Series []
 
 
--- | Create empty series
-series :: [(UTCTime, Double)] -> Series
+-- | Create series
+series :: [(UTCTime, a)] -> Series a
 series xs = Series $ map (\(x, y) -> DP x y) xs
 
 
@@ -49,17 +63,27 @@
 --
 -- >seriesFromSeconds [1, 2, 3] [41.3, 52.22, 3.0] == Series [DP 1970-01-01 00:00:01 UTC 2.3,DP 1970-01-01 00:00:02 UTC 4.5]
 --
-tsSeries :: [Integer] -> [Value] -> Series
+tsSeries :: [Integer] -> [a] -> Series a
 tsSeries ts vs = Series (zipWith DP idx vs)
     where idx = map (posixSecondsToUTCTime . fromIntegral) ts
 
 
+-- | Convert Time Series to list
+toList :: Series a -> [(UTCTime, a)]
+toList (Series xs) = map (\(DP x y) -> (x, y)) xs
+
+
+-- | Get only series values
+values :: Series a -> [a]
+values ts = map (\(_, y) -> y) (toList ts)
+
+
 -- | Get series size.
 -- Complexity O(n)
 --
 -- >size (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3
 --
-size :: Series -> Int
+size :: Series a -> Int
 size (Series xs) = length xs
 
 
@@ -69,10 +93,10 @@
 -- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 == Just 52.22
 -- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 == Nothing
 --
-valueAt :: Series -> UTCTime -> Maybe Value
+valueAt :: Series a -> UTCTime -> Maybe a
 valueAt (Series xs) ts = safeHead [y | DP x y <- xs, x == ts]
     where safeHead [] = Nothing
-          safeHead (a:_) = Just a
+          safeHead (i:_) = Just i
 
 
 -- | Return series subset
@@ -81,27 +105,7 @@
 -- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 3 == Series [DP 2 52.22, DP 3 3.0]
 -- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 23 == Series []
 --
-slice :: Series -> UTCTime -> UTCTime -> Series
+slice :: Series a -> UTCTime -> UTCTime -> Series a
 slice (Series xs) start end = Series [DP x y | DP x y <- xs, x >= start && x <= end]
 
 
--- | Return maximum value in the series
--- Complexity O(n)
---
--- >max (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 52.22
--- >max (Series []) == 0
---
-max :: Series -> Value
-max (Series xs) = foldl (\d (DP _ y) -> max' d y) 0.0 xs
-    where max' a b = if a > b then a else b
-
--- | Return maximum value in the series
--- Complexity O(n)
---
--- >min (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3.0
--- >min (Series []) == 0
---
-min :: Series -> Value
-min (Series xs) = foldl (\d (DP _ y) -> min' d y) maxValue xs
-    where min' a b = if a < b then a else b
-          maxValue = fromIntegral (maxBound :: Int)
diff --git a/src/Data/TimeSeries/Stats.hs b/src/Data/TimeSeries/Stats.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries/Stats.hs
@@ -0,0 +1,14 @@
+
+module Data.TimeSeries.Stats
+    ( mean
+    ) where
+
+import Prelude hiding (max, min)
+import Data.TimeSeries.Series (Series)
+
+
+-- | Return maximum value in the series
+mean :: Fractional a => Series a -> a
+mean xs = sum xs / fromIntegral (length xs)
+-- mean xs = (fromIntegral (length xs))
+
diff --git a/test-src/Data/TimeSeries/CSVSpec.hs b/test-src/Data/TimeSeries/CSVSpec.hs
deleted file mode 100644
--- a/test-src/Data/TimeSeries/CSVSpec.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-module Data.TimeSeries.CSVSpec (spec) where
-
-import Test.Hspec
-import Data.ByteString.Time (parseISODateTime)
-
-import qualified Data.TimeSeries as TS
-import qualified Data.TimeSeries.CSVReader as CSV
-
-
-spec :: Spec
-spec = do
-
-  describe "Reader" $ do
-
-    it "co2 test data" $ do
-        xs <- CSV.load parseISODateTime "testdata/co2.csv"
-        TS.size xs `shouldBe` 192
diff --git a/test-src/Data/TimeSeries/IO/CSVSpec.hs b/test-src/Data/TimeSeries/IO/CSVSpec.hs
new file mode 100644
--- /dev/null
+++ b/test-src/Data/TimeSeries/IO/CSVSpec.hs
@@ -0,0 +1,17 @@
+module Data.TimeSeries.IO.CSVSpec (spec) where
+
+import Test.Hspec
+import Data.Text.Time (parseISODateTime)
+
+import qualified Data.TimeSeries as TS
+import qualified Data.TimeSeries.IO.CSVReader as CSV
+
+
+spec :: Spec
+spec = do
+
+  describe "Reader" $ do
+
+    it "co2 test data" $ do
+        xs <- CSV.loadCSV CSV.HasHeader parseISODateTime "testdata/co2.csv"
+        TS.size xs `shouldBe` 192
diff --git a/test-src/Data/TimeSeries/SeriesSpec.hs b/test-src/Data/TimeSeries/SeriesSpec.hs
--- a/test-src/Data/TimeSeries/SeriesSpec.hs
+++ b/test-src/Data/TimeSeries/SeriesSpec.hs
@@ -1,7 +1,7 @@
 module Data.TimeSeries.SeriesSpec (spec) where
 
 import Test.Hspec
-import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)
 
 import qualified Data.TimeSeries as TS
 
@@ -16,6 +16,12 @@
         let values = [1.0, 2.0, 3.0]
         TS.size (TS.tsSeries idx values) `shouldBe` 3
 
+    it "toList" $ do
+        let idx = [1, 2, 3]
+        let values = [1.0, 2.0, 3.0]
+        let xs = TS.toList (TS.tsSeries idx values)
+        map (\(x, y) -> (utcTimeToPOSIXSeconds x, y)) xs `shouldBe` [(1, 1.0), (2, 2.0), (3, 3.0)]
+
     it "return data point value at given index" $ do
         let idx = [10, 20, 30]
         let values = [10.0, 12.0, 32.4]
@@ -40,10 +46,16 @@
         let end = posixSecondsToUTCTime $ fromIntegral 34
         TS.slice xs start end `shouldBe` TS.emptySeries
 
+    it "map over series" $ do
+        let xs = TS.tsSeries [1..] [10.0, 1.2, 32.4, 0.65, 11.0]
+        let ys = fmap (+ 2) xs
+        (TS.values ys)`shouldBe` [12.0, 3.2, 34.4, 2.65, 13.0]
+
     it "maximum value" $ do
-        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
-        TS.max xs `shouldBe` 32.4
+        let xs = TS.tsSeries [1..] [10.0, 1.2, 32.4, 0.65, 11.0]
+        maximum xs `shouldBe` 32.4
 
     it "minimum value" $ do
         let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
-        TS.min xs `shouldBe` 0.65
+        minimum xs `shouldBe` 0.65
+
diff --git a/test-src/Spec.hs b/test-src/Spec.hs
--- a/test-src/Spec.hs
+++ b/test-src/Spec.hs
@@ -1,9 +1,11 @@
 import Test.Hspec
 import qualified Data.TimeSeries.SeriesSpec
-import qualified Data.TimeSeries.CSVSpec
+import qualified Data.TimeSeries.StatsSpec
+import qualified Data.TimeSeries.IO.CSVSpec
 
 
 main :: IO ()
 main = hspec $ do
   describe "Series" Data.TimeSeries.SeriesSpec.spec
-  describe "CSV" Data.TimeSeries.CSVSpec.spec
+  describe "Statistcs" Data.TimeSeries.StatsSpec.spec
+  describe "CSV" Data.TimeSeries.IO.CSVSpec.spec
diff --git a/testdata/test-100K.csv b/testdata/test-100K.csv
new file mode 100644
# file too large to diff: testdata/test-100K.csv
diff --git a/timeseries.cabal b/timeseries.cabal
--- a/timeseries.cabal
+++ b/timeseries.cabal
@@ -1,5 +1,5 @@
 name:           timeseries
-version:        0.1.0
+version:        0.2.0
 synopsis:       Library for Time Series processing
 License:        BSD3
 License-file:   LICENSE
@@ -31,16 +31,18 @@
   build-depends:
                     base >= 4.7 && < 5,
                     bytestring < 0.11,
-                    bytestring-time < 1,
                     cassava >= 0.4 && < 0.5,
                     text < 2,
+                    text-time < 1,
                     time >= 1.5 && < 2,
                     vector < 0.12
   exposed-modules:
                     Data.TimeSeries
   other-modules:
                     Data.TimeSeries.Series,
-                    Data.TimeSeries.CSVReader
+                    Data.TimeSeries.Stats,
+                    Data.TimeSeries.IO.CSVReader
+                    Data.TimeSeries.IO.CSVWriter
 
 test-suite unit-tests
   type:             exitcode-stdio-1.0
@@ -52,17 +54,19 @@
                     hspec >=2 && <3,
                     QuickCheck >=2.6 && <3,
                     bytestring < 0.11,
-                    bytestring-time < 1,
                     cassava >= 0.4 && < 0.5,
                     text < 2,
+                    text-time < 1,
                     time >= 1.5 && < 2,
                     vector < 0.12
   other-modules:
                     Data.TimeSeries,
                     Data.TimeSeries.Series,
+                    Data.TimeSeries.Stats,
                     Data.TimeSeries.SeriesSpec
-                    Data.TimeSeries.CSVReader
-                    Data.TimeSeries.CSVSpec
+                    Data.TimeSeries.IO.CSVReader
+                    Data.TimeSeries.IO.CSVWriter
+                    Data.TimeSeries.IO.CSVSpec
   hs-source-dirs:
                     src,
                     test-src
