diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Ansigraph Changelog
 
+## Version 0.3
+
+* Change all IO operations to work over any `MonadIO`. Since GHC 8 this is available in `base`, so the dependency on `transformers` is only required for previous versions.
+
+* Support GHC versions back to 7.6.
+
+* Reexport the `Color` and `ColorIntensity` data types from `ansi-terminal` for full use of the range of ANSI colors without importing that package.
+
 ## Version 0.2
 
 * Improved method of displaying animations so that successive frames overwrite previous ones instead of generating many pages of output. This requires the addition of the `graphHeight :: Graphable a => a -> Int` type class method.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 
 __Terminal-based graphing via ANSI and Unicode__
 
-<img src="img/wavedemo.gif">
+![Complex wave demo](img/wavedemo.gif)
 
 ### Overview
 
diff --git a/ansigraph.cabal b/ansigraph.cabal
--- a/ansigraph.cabal
+++ b/ansigraph.cabal
@@ -1,5 +1,5 @@
 name:                ansigraph
-version:             0.2.0.0
+version:             0.3.0.0
 synopsis:            Terminal-based graphing via ANSI and Unicode
 
 description:         Ansigraph is an ultralightweight terminal-based graphing utility. It uses
@@ -59,9 +59,12 @@
                        System.Console.Ansigraph.Internal.Horizontal,
                        System.Console.Ansigraph.Internal.Matrix
 
-  build-depends:       base >=4.8 && <4.10,
+  build-depends:       base >=4.6 && <4.10,
                        ansi-terminal >=0.6 && <0.7
 
+  if (impl(ghc < 8.0))
+    build-depends:     transformers >= 0.3 && <0.5
+
   hs-source-dirs:      src
 
   default-language:    Haskell2010
@@ -70,6 +73,7 @@
                        -fno-warn-orphans
                        -fno-warn-unused-do-bind
                        -fno-warn-missing-signatures
+                       -fno-warn-unused-imports
 
 
 test-suite test-ansigraph
diff --git a/src/System/Console/Ansigraph/Core.hs b/src/System/Console/Ansigraph/Core.hs
--- a/src/System/Console/Ansigraph/Core.hs
+++ b/src/System/Console/Ansigraph/Core.hs
@@ -29,12 +29,18 @@
   -- *** Graphing options
   , GraphSettings (..)
 
-  -- *** Default options
+  -- **** Default options
   , graphDefaults
   , blue, pink, white, red, green
   , noColoring
 
   -- *** ANSI data
+  -- **** Basic types from ANSI package
+  , Color (..)
+  , ColorIntensity (..)
+
+
+-- **** Custom composite data types
   , AnsiColor (..)
   , Coloring (..)
 
@@ -83,6 +89,9 @@
   , posGraph
   , posAnim
 
+-- *** For clearing
+  , clearBack
+
 ) where
 
 import System.Console.Ansigraph.Internal.Core
@@ -90,9 +99,10 @@
 import System.Console.Ansigraph.Internal.Matrix
 
 import System.Console.ANSI
-import Control.Concurrent (threadDelay)
-import Control.Monad      (replicateM_)
-import Data.Complex       (Complex)
+import Control.Concurrent     (threadDelay)
+import Control.Monad          (replicateM_)
+import Data.Complex           (Complex)
+import Control.Monad.IO.Class (MonadIO, liftIO)
 
 
 -- | Things that ansigraph knows how to render at the terminal are instances of this class.
@@ -106,7 +116,7 @@
 class Graphable a where
 
   -- | Render a graph to standard output.
-  graphWith :: GraphSettings -> a -> IO ()
+  graphWith :: MonadIO m => GraphSettings -> a -> m ()
 
   -- | The number of vertical lines a graph occupies.
   graphHeight :: a -> Int
@@ -119,10 +129,12 @@
 
 ---- IO / ANSI helpers ----
 
-clearBack :: Int -> IO ()
+-- | Clear the last @n@ lines of terminal text. Used to make graph animations. Rexported as
+--   a handy convenience for other uses.
+clearBack :: MonadIO m => Int -> m ()
 clearBack n = do
-  putStr "\r"  -- return cursor to horizontal position 0
-  replicateM_ n (cursorUpLine 1 *> clearLine)
+  putStr' "\r"  -- return cursor to horizontal position 0
+  replicateM_ n (liftIO $ cursorUpLine 1 >> clearLine)
 
 -- | For some number of frames per second, return the corresponding time delta in microseconds.
 deltaFromFPS :: Int -> Int
@@ -131,34 +143,34 @@
 
 ---- Animation ----
 
-clearGraph :: Graphable a => a -> IO ()
+clearGraph :: MonadIO m => Graphable a => a -> m ()
 clearGraph = clearBack . graphHeight
 
-animationFrame :: Graphable a => GraphSettings -> a -> IO ()
+animationFrame :: MonadIO m => Graphable a => GraphSettings -> a -> m ()
 animationFrame s x = do
   graphWith s x
-  threadDelay . deltaFromFPS . framerate $ s
+  liftIO . threadDelay . deltaFromFPS . framerate $ s
   clearGraph x
 
 -- | Any list of a 'Graphable' type can be made into an animation, by
 --   'graph'ing each element with a time delay and screen-clear after each.
 --   'GraphSettings' are used to determine the time delta and any coloring/scaling options.
-animateWith :: Graphable a => GraphSettings -> [a] -> IO ()
+animateWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m ()
 animateWith _ []       = return ()
 animateWith s [x]      = graphWith s x
-animateWith s (x:y:zs) = animationFrame s x *> animateWith s (y:zs)
+animateWith s (x:y:zs) = animationFrame s x >> animateWith s (y:zs)
 
 -- | Perform 'animateWith' using default options. Equivalent to 'graph'ing each member
 --   of the supplied list with a short delay and screen-clear after each.
-animate :: Graphable a => [a] -> IO ()
+animate :: MonadIO m => Graphable a => [a] -> m ()
 animate = animateWith graphDefaults
 
 -- | Like 'animateWith', only it does not leave the final frame of the animation visible.
-transientAnimWith :: Graphable a => GraphSettings -> [a] -> IO ()
+transientAnimWith :: MonadIO m => Graphable a => GraphSettings -> [a] -> m ()
 transientAnimWith = mapM_ . animationFrame
 
 -- | Like 'animate', only it does not leave the final frame of the animation visible.
-transientAnim :: Graphable a => [a] -> IO ()
+transientAnim :: (MonadIO m, Graphable a) => [a] -> m ()
 transientAnim = transientAnimWith graphDefaults
 
 
diff --git a/src/System/Console/Ansigraph/Examples.hs b/src/System/Console/Ansigraph/Examples.hs
--- a/src/System/Console/Ansigraph/Examples.hs
+++ b/src/System/Console/Ansigraph/Examples.hs
@@ -24,6 +24,8 @@
 import System.Console.ANSI
 import Control.Monad      (forM_)
 import Data.Complex       (Complex (..), cis, realPart)
+-- for GHC <= 7.8
+import Control.Applicative
 
 
 ---- Wave Demo ----
@@ -77,13 +79,14 @@
 fromRealMs = zipWith fromRealVs
 
 vox :: Num a => [a] -> [a] -> [a]
-vox v w = concat $ map (flip vscale w) v
+vox v w = concatMap (`vscale` w) v
 
 -- matrix tensor product
-stepOne, stepTwo, mox :: Num a => [[a]] -> [[a]] -> [[a]]
-stepOne m1 m2 = concat $ map (replicate (length m2)) m1
-stepTwo m1 m2 = concat $ replicate (length m1) m2
-mox     m1 m2 = zipWith vox (stepOne m1 m2) (stepTwo m1 m2)
+mox :: Num a => [[a]] -> [[a]] -> [[a]]
+mox m1 m2 = zipWith vox (stepOne m1 m2) (stepTwo m1 m2)
+  where stepOne, stepTwo :: [[a]] -> [[a]] -> [[a]]
+        stepOne x y = concatMap (replicate (length y)) x
+        stepTwo x y = concat $ replicate (length x) y
 
 
 ---- Complex matrix example ----
@@ -116,7 +119,7 @@
 ---- Real matrix example ----
 
 ry :: Double -> [[Double]]
-ry t = [[cos t, 0, (sin t)]
+ry t = [[cos t, 0, sin t]
        ,[0, 1, 0]
        ,[-(sin t),0,cos t]]
 
diff --git a/src/System/Console/Ansigraph/Internal/Core.hs b/src/System/Console/Ansigraph/Internal/Core.hs
--- a/src/System/Console/Ansigraph/Internal/Core.hs
+++ b/src/System/Console/Ansigraph/Internal/Core.hs
@@ -4,6 +4,9 @@
 
 import System.Console.ANSI
 import System.IO (hFlush, stdout)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+-- for GHC <= 7.8
+import Control.Applicative
 
 ---- Basics ----
 
@@ -51,6 +54,19 @@
 -- | 'Dull' 'Green' – used as the default foreground color for negative imaginary component.
 green = AnsiColor Dull Green
 
+-- | 'Dull' 'Black'.
+black  = AnsiColor Dull Blue
+
+-- | 'Vivid' 'Yellow'.
+yellow  = AnsiColor Vivid Yellow
+
+-- | 'Vivid' 'Magenta'.
+magenta  = AnsiColor Vivid Magenta
+
+-- | 'Vivid' 'Cyan'.
+cyan  = AnsiColor Vivid Cyan
+
+
 -- | Default graph settings.
 graphDefaults = GraphSettings blue pink red green white white 15
 
@@ -84,14 +100,6 @@
 invert :: Coloring -> Coloring
 invert (Coloring fg bg) = Coloring bg fg
 
--- | The SGR command corresponding to a particular 'ConsoleLayer' and 'AnsiColor'.
-interpAnsiColor :: ConsoleLayer -> AnsiColor -> SGR
-interpAnsiColor l (AnsiColor i c) = SetColor l i c
-
--- | Set the given 'AnsiColor' on the given 'ConsoleLayer'.
-setColor :: ConsoleLayer -> AnsiColor -> IO ()
-setColor l c = setSGR [interpAnsiColor l c]
-
 -- | Easily create a 'Coloring' by specifying the background 'AnsiColor' and no custom foreground.
 fromBG :: AnsiColor -> Coloring
 fromBG c = Coloring Nothing (Just c)
@@ -100,53 +108,61 @@
 fromFG :: AnsiColor -> Coloring
 fromFG c = Coloring (Just c) Nothing
 
+-- | The SGR command corresponding to a particular 'ConsoleLayer' and 'AnsiColor'.
+interpAnsiColor :: ConsoleLayer -> AnsiColor -> SGR
+interpAnsiColor l (AnsiColor i c) = SetColor l i c
+
 -- | Produce a (possibly empty) list of 'SGR' commands from a 'ConsoleLayer' and 'AnsiColor'.
 --   An empty 'SGR' list is equivalent to 'Reset'.
 sgrList :: ConsoleLayer -> Maybe AnsiColor -> [SGR]
-sgrList l = fmap (interpAnsiColor l) . maybe [] (\x -> [x])
+sgrList l = fmap (interpAnsiColor l) . maybe [] pure
 
+-- | Set the given 'AnsiColor' on the given 'ConsoleLayer'.
+setColor :: MonadIO m => ConsoleLayer -> AnsiColor -> m ()
+setColor l c = liftIO $ setSGR [interpAnsiColor l c]
+
 -- | Apply both foreground and background color contained in a 'Coloring'.
-applyColoring :: Coloring -> IO ()
-applyColoring (Coloring fg bg) = do
+applyColoring :: MonadIO m => Coloring -> m ()
+applyColoring (Coloring fg bg) = liftIO $ do
   setSGR [Reset]
   setSGR $ sgrList Foreground fg ++ sgrList Background bg
 
 -- | Clear any SGR settings and then flush stdout.
-clear :: IO ()
-clear = setSGR [Reset] *> hFlush stdout
+clear :: MonadIO m => m ()
+clear = liftIO $ setSGR [Reset] >> hFlush stdout
 
+putStrLn', putStr' :: MonadIO m => String -> m ()
+putStrLn' = liftIO . putStrLn
+putStr' = liftIO . putStr
+
 -- | Clear any SGR settings, flush stdout and print a new line.
-clearLn :: IO ()
-clearLn = clear *> putStrLn ""
+clearLn :: MonadIO m => m ()
+clearLn = clear >> putStrLn' ""
 
 -- | Use a particular ANSI 'Coloring' to print a string at the terminal (without a new line),
 --   then clear all ANSI SGR codes and flush stdout.
-colorStr :: Coloring -> String -> IO ()
+colorStr :: MonadIO m => Coloring -> String -> m ()
 colorStr c s = do
   applyColoring c
-  putStr s
+  putStr' s
   clear
 
 -- | Use a particular ANSI 'Coloring' to print a string at the terminal,
 --   then clear all ANSI SGR codes, flush stdout and print a new line.
-colorStrLn :: Coloring -> String -> IO ()
+colorStrLn :: MonadIO m => Coloring -> String -> m ()
 colorStrLn c s = do
   applyColoring c
-  putStr s
+  putStr' s
   clearLn
 
 -- | Like 'colorStr' but prints bold text.
-boldStr :: Coloring -> String -> IO ()
+boldStr :: MonadIO m => Coloring -> String -> m ()
 boldStr c s = do
   applyColoring c
-  setSGR [SetConsoleIntensity BoldIntensity]
-  putStr s
+  liftIO $ setSGR [SetConsoleIntensity BoldIntensity]
+  putStr' s
   clear
 
 -- | Like 'colorStrLn' but prints bold text.
-boldStrLn :: Coloring -> String -> IO ()
-boldStrLn c s = do
-  applyColoring c
-  setSGR [SetConsoleIntensity BoldIntensity]
-  putStr s
-  clearLn
+boldStrLn :: MonadIO m => Coloring -> String -> m ()
+boldStrLn c s = boldStr c s >> putStrLn' ""
diff --git a/src/System/Console/Ansigraph/Internal/Horizontal.hs b/src/System/Console/Ansigraph/Internal/Horizontal.hs
--- a/src/System/Console/Ansigraph/Internal/Horizontal.hs
+++ b/src/System/Console/Ansigraph/Internal/Horizontal.hs
@@ -11,7 +11,11 @@
 import System.Console.Ansigraph.Internal.Core
 
 import Data.Complex
+import Control.Monad.IO.Class (MonadIO)
+-- for GHC <= 7.8
+import Control.Applicative
 
+
 ---- Graphing Infrastructure  ----
 
 barChars = "█▇▆▅▄▃▂▁ "
@@ -74,13 +78,13 @@
 
 -- | ANSI based display for positive real vectors. Primarily invoked via 'graph', 'graphWith',
 --   'animate', 'animateWith'.
-displayPV :: GraphSettings -> [Double] -> IO ()
+displayPV :: MonadIO m => GraphSettings -> [Double] -> m ()
 displayPV s l = let (rp,_) = renderRV l
                     rcol   = realColors s in colorStrLn rcol rp
 
 -- | ANSI based display for real vectors. Primarily invoked via 'graph', 'graphWith',
 --   'animate', 'animateWith'.
-displayRV :: GraphSettings -> [Double] -> IO ()
+displayRV :: MonadIO m => GraphSettings -> [Double] -> m ()
 displayRV s l = let (rp,rm) = renderRV l
                     rcol    = realColors s
   in do colorStrLn rcol          rp
@@ -88,7 +92,7 @@
 
 -- | ANSI based display for complex vectors. Primarily invoked via 'graph', 'graphWith',
 --   'animate', 'animateWith'.
-displayCV :: GraphSettings -> [Complex Double] -> IO ()
+displayCV :: MonadIO m => GraphSettings -> [Complex Double] -> m ()
 displayCV s l = let (rp,rm,ip,im) = renderCV l
                     (rcol,icol)   = colorSets s
   in do colorStrLn rcol          rp
diff --git a/src/System/Console/Ansigraph/Internal/Matrix.hs b/src/System/Console/Ansigraph/Internal/Matrix.hs
--- a/src/System/Console/Ansigraph/Internal/Matrix.hs
+++ b/src/System/Console/Ansigraph/Internal/Matrix.hs
@@ -10,7 +10,11 @@
 
 import Data.Complex
 import Data.List (intersperse)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+-- for GHC <= 7.8
+import Control.Applicative
 
+
 ---- Matrices ----
 
 mmap :: (a -> b) -> [[a]] -> [[b]]
@@ -34,12 +38,12 @@
 elemChar (MatElement _ c) = c
 
 
-putRealElement :: GraphSettings -> MatElement -> IO ()
+putRealElement :: MonadIO m => GraphSettings -> MatElement -> m ()
 putRealElement s (MatElement b c) = colorStr clring (c : " ")
   where clr    = if b then realNegColor s else realColor s
         clring = mkColoring clr (realBG s)
 
-putImagElement :: GraphSettings -> MatElement -> IO ()
+putImagElement :: MonadIO m => GraphSettings -> MatElement -> m ()
 putImagElement s (MatElement b c) = colorStr clring $ c : " "
   where clr    = if b then imagNegColor s else imagColor s
         clring = mkColoring clr (imagBG s)
@@ -60,26 +64,26 @@
 matShow :: [[Double]] -> [String]
 matShow = mmap elemChar . matElements
 
-newline = putStrLn ""
+newline = putStrLn' ""
 
 intersperse' x l = intersperse x l ++ [x]
 
 
 -- | Use ANSI coloring (specified by an 'GraphSettings') to visually display a Real matrix.
-displayMat :: GraphSettings -> [[Double]] -> IO ()
-displayMat s = sequence_ . concat . intersperse' [newline] . displayRealMat s
+displayMat :: MonadIO m => GraphSettings -> [[Double]] -> m ()
+displayMat s = liftIO . sequence_ . concat . intersperse' [newline] . displayRealMat s
 
 -- | Use ANSI coloring (specified by a 'GraphSettings') to visually display a Real matrix.
-displayRealMat :: GraphSettings -> [[Double]] -> [[IO ()]]
+displayRealMat :: MonadIO m => GraphSettings -> [[Double]] -> [[m ()]]
 displayRealMat s = mmap (putRealElement s) . matElements
 
 -- | Use ANSI coloring (specified by a 'GraphSettings') to visually display a Real matrix.
-displayImagMat :: GraphSettings -> [[Double]] -> [[IO ()]]
+displayImagMat :: MonadIO m => GraphSettings -> [[Double]] -> [[m ()]]
 displayImagMat s = mmap (putImagElement s) . matElements
 
 -- | Use ANSI coloring (specified by an 'GraphSettings') to visually display a Complex matrix.
-displayCMat :: GraphSettings -> [[Complex Double]] -> IO ()
-displayCMat s m = sequence_ . concat . intersperse' [newline] $
+displayCMat :: MonadIO m => GraphSettings -> [[Complex Double]] -> m ()
+displayCMat s m = liftIO . sequence_ . concat . intersperse' [newline] $
   zipWith (\xs ys -> xs ++ putStr " " : ys)
           (displayRealMat s $ mmap realPart m)
           (displayImagMat s $ mmap imagPart m)
diff --git a/test/test-ansigraph.hs b/test/test-ansigraph.hs
--- a/test/test-ansigraph.hs
+++ b/test/test-ansigraph.hs
@@ -6,6 +6,9 @@
 import System.Console.Ansigraph.Examples (wave)
 import Data.Complex
 import Data.Char (isSpace)
+-- for GHC <= 7.8
+import Control.Applicative
+
 
 
 ---- For horizontal graphing tests ----
