diff --git a/calculator.cabal b/calculator.cabal
--- a/calculator.cabal
+++ b/calculator.cabal
@@ -1,9 +1,12 @@
 name:                calculator
-version:             0.2.2.1
+version:             0.3.0.0
 synopsis:            A calculator repl.
 description:         A calculator repl that processes mathematical expressions.
                      Does basic arithmetic, and provides pre-defined basic mathematical functions.
+                     .
                      Provides binding functionality for variables and functions.
+                     .
+                     Optionally provides plotting support.
 homepage:            https://github.com/sumitsahrawat/calculator
 license:             GPL-2
 license-file:        LICENSE
@@ -15,6 +18,10 @@
 -- extra-source-files:  
 cabal-version:       >=1.10
 
+flag plot-gtk-ui
+  default:             False
+  description:         Use plot-gtk-ui to provide plotting commands
+
 executable calculator
   main-is:             Main.hs
   other-modules:       Calculator.Evaluator.Base
@@ -42,6 +49,11 @@
   hs-source-dirs:      src/
   ghc-options:         -Wall
   default-language:    Haskell2010
+  if flag(plot-gtk-ui)
+     cpp-options:      -DPLOT
+     build-depends:    plot-gtk-ui >=0.0.2.0
+                     , gtk >=0.13.0 && <0.14.0
+                     , transformers >= 0.4.2.0
 
 test-suite model-test-arithmetic
   type:                exitcode-stdio-1.0
diff --git a/src/Calculator/Evaluator/Base.hs b/src/Calculator/Evaluator/Base.hs
--- a/src/Calculator/Evaluator/Base.hs
+++ b/src/Calculator/Evaluator/Base.hs
@@ -5,41 +5,25 @@
 import           Calculator.Evaluator.Statement (evalStat)
 import           Calculator.Parser.Statement    (parseStat)
 import           Calculator.Prim.Bindings       (Bindings, mkBind)
-import           Calculator.Prim.Expr           (Expr (..))
+import           Calculator.Prim.Result         (Result (..))
 
 --------------------------------------------------------------------------------
 
 import           Control.Applicative            ((<*))
-import           Data.List                      (nub)
 import           Text.ParserCombinators.Parsec  (eof, parse, spaces)
 
 --------------------------------------------------------------------------------
 
-eval :: Bindings -> String -> Either Expr Bindings
-eval b i = case parse (spaces >> parseStat <* spaces <* eof) "Statement" i of
-             Left e  -> Left . Message . tail . lines . show $ e
-             Right s -> evalStat b s
-
---------------------------------------------------------------------------------
-
-result :: Either Expr Bindings -> Either String Bindings
-result e =
-  case e of
-   Left (Constant c) -> Left $ " == " ++ show c
-   Left (Message x)  -> Left . init . unlines . map (" -!- " ++ ) . nub $ x
-   Right b           -> Right b
-   Left _            -> Left " ~~ Erroneous Result ~~"
-
---------------------------------------------------------------------------------
-
-evaluate :: Bindings -> String -> Either String Bindings
-evaluate b s = result $ eval b s
+evaluate :: Bindings -> String -> Result
+evaluate b i = case parse (spaces >> parseStat <* spaces <* eof) "Statement" i of
+                 Left e  -> Error . show $ e
+                 Right s -> evalStat b s
 
 --------------------------------------------------------------------------------
 
 evalTest :: String -> String
-evalTest s = case eval (mkBind [] []) s of
-               Left (Constant n) -> show n
-               _                 -> ""
+evalTest s = case evaluate (mkBind [] []) s of
+               Value n -> show n
+               _       -> ""
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Evaluator/Cmd.hs b/src/Calculator/Evaluator/Cmd.hs
--- a/src/Calculator/Evaluator/Cmd.hs
+++ b/src/Calculator/Evaluator/Cmd.hs
@@ -1,30 +1,87 @@
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies     #-}
+
 module Calculator.Evaluator.Cmd (evalCmd) where
 
 --------------------------------------------------------------------------------
 
-import           Calculator.Evaluator.Expr   (evalExpr)
-import           Calculator.Evaluator.Func   (execFunc)
-import           Calculator.Help             (help)
-import           Calculator.Prim.Bindings    (Bindings, addFun, addVar, display)
-import           Calculator.Prim.Cmd         (Cmd (..))
-import           Calculator.Prim.Definitions (defBinds)
-import           Calculator.Prim.Expr        (Expr (Message, Constant))
-import           Calculator.Prim.Function    (testFunc)
+import           Calculator.Evaluator.Expr      (evalExpr)
+import           Calculator.Evaluator.Func      (execFunc)
+import           Calculator.Help                (help)
+import           Calculator.Prim.Bindings       (Bindings, addFun, addVar,
+                                                 display)
+import           Calculator.Prim.Cmd            (Cmd (..))
+import           Calculator.Prim.Definitions    (defBinds)
+import           Calculator.Prim.Expr           (Expr (Message, Constant))
+import           Calculator.Prim.Function       (testFunc)
+import           Calculator.Prim.Result         (Result (..))
 
 --------------------------------------------------------------------------------
 
-evalCmd :: Bindings -> Cmd -> Either [String] Bindings
-evalCmd _ Help    = Left help
-evalCmd b Display = Left $ display b
-evalCmd _ Reset   = Right defBinds
+#ifdef PLOT
+
+import           Calculator.Prim.Bindings       (getFun)
+import           Calculator.Prim.Function       (Function, apply, arity)
+
+import           Graphics.Rendering.Plot.Gtk.UI (plotWithArity)
+import           Graphics.UI.Gtk                (initGUI, mainGUI)
+
+import           Data.List                      (foldl1')
+import           Data.Maybe
+
+#endif
+
+--------------------------------------------------------------------------------
+
+evalCmd :: Bindings -> Cmd -> Result
+evalCmd _ Help    = Text . unlines $ help
+evalCmd b Display = Text . unlines . display $ b
+evalCmd _ Reset   = NewBindings defBinds
 evalCmd b (Assign s e)   =
     case evalExpr b e of
-      Message xxs -> Left xxs
-      Constant c  -> Right $ addVar (s, c) b
-      _           -> Left [" ~~ Erroneous Result ~~ "]
+      Message xxs -> Error . unlines $ xxs
+      Constant c  -> NewBindings . addVar (s, c) $ b
+      _           -> Error " ~~ Erroneous Result ~~ "
 evalCmd b fun@(Func i _ _) = let f = execFunc b fun
                              in case testFunc f 0 of
-                                  Nothing -> Right $ addFun (i, f) b
-                                  Just ms -> Left ms
+                                  Nothing -> NewBindings . addFun (i, f) $ b
+                                  Just ms -> Error . unlines $ ms
+
+--------------------------------------------------------------------------------
+
+#ifdef PLOT
+
+evalCmd b (Plot s rs) =
+    case getFun s b of
+      Nothing -> Error $ "Unknown function: " ++ s
+      Just f  -> let pairMap fn (x, y) = (fn x, fn y)
+                     rangeExps = map (pairMap (evalExpr b)) rs
+                     rangeErrs = map (uncurry grabMessage) rangeExps
+                     allErrors = foldl1' grabMessage rangeErrs
+                     ranges    = map (pairMap (\(Constant c) -> c)) rangeExps
+                     fromMsg   = (\(Message ms) -> ms)
+                 in if null . fromMsg $ allErrors
+                    then plotFunction f ranges
+                    else Error . unlines . fromMsg $ allErrors
+
+grabMessage :: Expr -> Expr -> Expr
+grabMessage (Message m1)   (Message m2) = Message (m1 ++ m2)
+grabMessage m1@(Message _) _            = m1
+grabMessage _            m2@(Message _) = m2
+grabMessage _              _            = Message []
+
+plotFunction :: Function -> [(Double, Double)] -> Result
+plotFunction f ranges =
+    if length ranges /= arity f
+    then Error $ "Invalid parameters: " ++
+             "Required " ++ show (arity f) ++ " range(s). " ++
+             "Provided " ++ show (length ranges) ++ "."
+    else Action $ do
+      _ <- initGUI
+      fromJust $ plotWithArity (arity f) ((\(Right x) -> x) . apply f) ranges
+      mainGUI
+
+#endif
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Evaluator/Expr.hs b/src/Calculator/Evaluator/Expr.hs
--- a/src/Calculator/Evaluator/Expr.hs
+++ b/src/Calculator/Evaluator/Expr.hs
@@ -3,8 +3,8 @@
 --------------------------------------------------------------------------------
 
 import           Calculator.Prim.Bindings (Bindings, getFun, getVar)
-import           Calculator.Prim.Expr     (Expr (..), Operator (..),
-                                           joinMessage, isConst)
+import           Calculator.Prim.Expr     (Expr (..), Operator (..), isConst,
+                                           joinMessage)
 import           Calculator.Prim.Function (Function (..))
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Evaluator/Func.hs b/src/Calculator/Evaluator/Func.hs
--- a/src/Calculator/Evaluator/Func.hs
+++ b/src/Calculator/Evaluator/Func.hs
@@ -10,7 +10,7 @@
 
 --------------------------------------------------------------------------------
 
-execFunc :: Bindings -> Cmd -> Function Double
+execFunc :: Bindings -> Cmd -> Function
 execFunc b (Func _ args e) =
     mkFuncEither (length args) $ \xs ->
         case evalExpr (appendVars (zip args xs) b) e of
diff --git a/src/Calculator/Evaluator/Statement.hs b/src/Calculator/Evaluator/Statement.hs
--- a/src/Calculator/Evaluator/Statement.hs
+++ b/src/Calculator/Evaluator/Statement.hs
@@ -5,16 +5,19 @@
 import           Calculator.Evaluator.Cmd  (evalCmd)
 import           Calculator.Evaluator.Expr (evalExpr)
 import           Calculator.Prim.Bindings  (Bindings)
-import           Calculator.Prim.Expr      (Expr (Message))
+import           Calculator.Prim.Expr      (Expr (Message, Constant))
+import           Calculator.Prim.Result    (Result (..))
 import           Calculator.Prim.Statement (Statement (..))
 
 --------------------------------------------------------------------------------
 
-evalStat :: Bindings -> Statement -> Either Expr Bindings
-evalStat b stat = case stat of
-                   Expression e -> Left $ evalExpr b e
-                   Command c    -> case evalCmd b c of
-                                     Left s   -> Left . Message $ s
-                                     Right b' -> Right b'
+evalStat :: Bindings -> Statement -> Result
+evalStat b stat =
+    case stat of
+      Expression e -> case evalExpr b e of
+                        Constant c -> Value c
+                        Message  t -> Error . unlines $ t
+                        _          -> Error "Internal error: evalStat"
+      Command c    -> evalCmd b c
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Help.hs b/src/Calculator/Help.hs
--- a/src/Calculator/Help.hs
+++ b/src/Calculator/Help.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 module Calculator.Help (help) where
 
 --------------------------------------------------------------------------------
@@ -18,6 +20,9 @@
        , "   :func f(x)=x+1     -- Binds f(x) to \"x + 1\""
        , "   :func f(x,y)=x+y   -- Binds f(x) to \"x + y\""
        , "   :reset             -- Reset variable and function bindings"
+#ifdef PLOT
+       , "   :plot              -- For plotting, detailed below"
+#endif
        , "   :show              -- Display all variable bindings"
        , "   :? or :help        -- Display this help message"
        , bold "Unary Operators: " ++ intersperse ' ' (map fst unaryOps)
@@ -29,6 +34,14 @@
        , "   :func f ( x ) = x + x + x     -- works"
        , " but not everywhere, e.g in commands"
        , "   : func ...                    -- doesn't work"
+#ifdef PLOT
+       , bold "Plotting: "
+       , "   :plot f (0, 1)"
+       , "   -- Plot a single argument function 'f' in range (0, 1)"
+       , "   :plot f (0, 1) (1, 2)"
+       , "   -- Plot a two argument function 'f' in range (0, 1)"
+       , "   -- where the second argument can be varied between 1 and 2"
+#endif
        ]
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Parser/Cmd.hs b/src/Calculator/Parser/Cmd.hs
--- a/src/Calculator/Parser/Cmd.hs
+++ b/src/Calculator/Parser/Cmd.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 module Calculator.Parser.Cmd
     ( parseCmd
     , parseAssignCmd
@@ -12,6 +14,12 @@
 import           Calculator.Parser.Expr        (parseExpr)
 import           Calculator.Prim.Cmd           (Cmd (..))
 
+#ifdef PLOT
+
+import           Calculator.Prim.Expr          (Expr)
+
+#endif
+
 --------------------------------------------------------------------------------
 
 import           Control.Applicative           ((<*))
@@ -24,7 +32,7 @@
 parseCmd = char ':' >> parseCmd'
 
 --------------------------------------------------------------------------------
--- cmd' -> show | help | reset | assign
+-- cmd' -> show | help | reset | assign | plot
 
 parseCmd' :: Parser Cmd
 parseCmd' = parseShow
@@ -32,6 +40,9 @@
          <|> parseReset
          <|> parseAssignCmd
          <|> parseFuncCmd
+#ifdef PLOT
+         <|> parsePlotCmd
+#endif
 
 --------------------------------------------------------------------------------
 -- help -> "?" | "help"
@@ -40,7 +51,7 @@
 parseHelp = (string "?" <|> string "help") >> spaces >> return Help
 
 --------------------------------------------------------------------------------
--- reset -> "reset"
+-- show -> "show"
 
 parseShow :: Parser Cmd
 parseShow = string "show" >> spaces >> return Display
@@ -50,6 +61,35 @@
 
 parseReset :: Parser Cmd
 parseReset = string "reset" >> spaces >> return Reset
+
+--------------------------------------------------------------------------------
+-- plot -> "plot" id
+
+#ifdef PLOT
+
+parsePlotCmd :: Parser Cmd
+parsePlotCmd = do
+  _ <- string "plot"
+  _ <- spaces
+  f <- parseId
+  _ <- spaces
+  r <- pairDoubles `sepBy1` spaces
+  return $ Plot f r
+
+pairDoubles :: Parser (Expr, Expr)
+pairDoubles = do
+  _ <- char '('
+  _ <- spaces
+  l <- parseExpr
+  _ <- spaces
+  _ <- char ','
+  _ <- spaces
+  u <- parseExpr
+  _ <- spaces
+  _ <- char ')'
+  return (l, u)
+
+#endif
 
 --------------------------------------------------------------------------------
 -- assignCmd -> "var" id "=" expr
diff --git a/src/Calculator/Prim/Bindings.hs b/src/Calculator/Prim/Bindings.hs
--- a/src/Calculator/Prim/Bindings.hs
+++ b/src/Calculator/Prim/Bindings.hs
@@ -22,13 +22,13 @@
 -- | Represents variable and function bindings
 data Bindings = Bindings {
       varMap :: M.Map String Double
-    , funMap :: M.Map String (Function Double)
+    , funMap :: M.Map String Function
     }
 
 --------------------------------------------------------------------------------
 
 -- | Make a new binding from two alists
-mkBind :: [(String, Double)] -> [(String, Function Double)] -> Bindings
+mkBind :: [(String, Double)] -> [(String, Function)] -> Bindings
 mkBind vars funs = Bindings {
                      varMap = M.fromList vars
                    , funMap = M.fromList funs
@@ -51,11 +51,11 @@
 --------------------------------------------------------------------------------
 
 -- | Add a @Function@ to @Bindings@
-addFun :: (String, Function Double) -> Bindings -> Bindings
+addFun :: (String, Function) -> Bindings -> Bindings
 addFun (s, f) b = b { funMap = M.insert s f (funMap b) }
 
 -- | Get a @Function@ from @Bindings@
-getFun :: String -> Bindings -> Maybe (Function Double)
+getFun :: String -> Bindings -> Maybe Function
 getFun s b = M.lookup s (funMap b)
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Prim/Cmd.hs b/src/Calculator/Prim/Cmd.hs
--- a/src/Calculator/Prim/Cmd.hs
+++ b/src/Calculator/Prim/Cmd.hs
@@ -1,5 +1,7 @@
-module Calculator.Prim.Cmd ( Cmd (..) ) where
+{-# LANGUAGE CPP #-}
 
+module Calculator.Prim.Cmd (Cmd (..)) where
+
 --------------------------------------------------------------------------------
 
 import           Calculator.Prim.Expr (Expr)
@@ -12,5 +14,8 @@
          | Help
          | Reset
          | Display
+#ifdef PLOT
+         | Plot String [(Expr, Expr)]
+#endif
 
 --------------------------------------------------------------------------------
diff --git a/src/Calculator/Prim/Definitions.hs b/src/Calculator/Prim/Definitions.hs
--- a/src/Calculator/Prim/Definitions.hs
+++ b/src/Calculator/Prim/Definitions.hs
@@ -35,7 +35,7 @@
 --------------------------------------------------------------------------------
 
 -- | List of pre-defined @Functions@
-defFuns :: [(String, Function Double)]
+defFuns :: [(String, Function)]
 defFuns = map (second oneArg)
            [ ("sin", sin)
            , ("cos", cos)
diff --git a/src/Calculator/Prim/Function.hs b/src/Calculator/Prim/Function.hs
--- a/src/Calculator/Prim/Function.hs
+++ b/src/Calculator/Prim/Function.hs
@@ -1,6 +1,5 @@
 module Calculator.Prim.Function
-    ( Function
-    , apply
+    ( Function (..)
     , mkFunc
     , mkFuncEither
     , oneArg
@@ -11,33 +10,33 @@
 --------------------------------------------------------------------------------
 
 -- | Represents a function, where rank == No. of arguments
-data Function a = Function {
+data Function = Function {
       arity :: Int
-    , apply :: [a] -> Either [String] a
+    , apply :: [Double] -> Either [String] Double
     }
 
 --------------------------------------------------------------------------------
 
 -- | Make a @Function@ out of an arity and another function
-mkFunc :: Int -> ([a] -> a) -> Function a
+mkFunc :: Int -> ([Double] -> Double) -> Function
 mkFunc a f = mkFuncEither a (Right . f)
 
 --------------------------------------------------------------------------------
 
 -- | Make a @Function@ with an arity using an error giving function
-mkFuncEither :: Int -> ([a] -> Either [String] a) -> Function a
+mkFuncEither :: Int -> ([Double] -> Either [String] Double) -> Function
 mkFuncEither a f = Function { arity = a , apply = g }
     where g xs = if length xs == a
                  then f xs
-                 else Left $ [ "Invalid no. of arguments"
-                             , "Required: " ++ show a
-                             , "Provided: " ++ show (length xs)
-                             ]
+                 else Left [ "Invalid no. of arguments"
+                           , "Required: " ++ show a
+                           , "Provided: " ++ show (length xs)
+                           ]
 
 --------------------------------------------------------------------------------
 
 -- | Make a @Function@ out of a single argument function
-oneArg :: (a -> a) -> Function a
+oneArg :: (Double -> Double) -> Function
 oneArg f = mkFunc 1 (\ [x] -> f x)
 
 --------------------------------------------------------------------------------
@@ -45,7 +44,7 @@
 -- | Partially apply a function, thus creating a one-argument function.
 -- To be used for parametrized functions, e.g getting g(x) = f(x,1,2)
 -- this retains the free-variable 'x'
-partial :: Function a -> [a] -> a -> Maybe a
+partial :: Function -> [Double] -> Double -> Maybe Double
 partial f xs x = case apply f (x:xs) of
                    Left _  -> Nothing
                    Right v -> Just v
@@ -54,7 +53,7 @@
 
 -- | Test a @Function@ with some value t, useful for sanity checking
 -- while adding a @Function@ to a @Bindings@
-testFunc :: Function a -> a -> Maybe [String]
+testFunc :: Function -> Double -> Maybe [String]
 testFunc f t = case apply f (replicate (arity f) t) of
                  Left ms -> Just ms
                  Right _ -> Nothing
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 module Main where
 
 --------------------------------------------------------------------------------
@@ -10,6 +12,7 @@
 import           Calculator.Evaluator.Base   (evaluate)
 import           Calculator.Prim.Bindings    (Bindings)
 import           Calculator.Prim.Definitions (defBinds)
+import           Calculator.Prim.Result      (Result (..))
 
 --------------------------------------------------------------------------------
 
@@ -18,6 +21,12 @@
 
 --------------------------------------------------------------------------------
 
+#ifdef PLOT
+import           Control.Monad.IO.Class      (liftIO)
+#endif
+
+--------------------------------------------------------------------------------
+
 type Repl a = InputT IO a
 
 --------------------------------------------------------------------------------
@@ -27,9 +36,21 @@
   input <- getInputLine $ color Red True "calc> "
   case input of
     Nothing  -> return ()
-    Just inp -> case evaluate b inp of
-                  Left s   -> outputStrLn s >> repl b
-                  Right b' -> repl b'
+    Just inp -> process b inp
+
+padOut :: Bindings -> String -> String -> Repl ()
+padOut b s m = do outputStr . unlines . map (s ++) . lines $ m
+                  repl b
+
+process :: Bindings -> String -> Repl ()
+process b inp = case evaluate b inp of
+                  Value c -> padOut b " == " $ show c
+                  Text t  -> padOut b " ~~ " t
+                  Error e -> padOut b " !! " e
+                  NewBindings b' -> repl b'
+#ifdef PLOT
+                  Action io      -> liftIO io >> repl b
+#endif
 
 --------------------------------------------------------------------------------
 
