diff --git a/Development/Shake.hs b/Development/Shake.hs
--- a/Development/Shake.hs
+++ b/Development/Shake.hs
@@ -96,9 +96,6 @@
 import Development.Shake.Types
 import Development.Shake.Core
 import Development.Shake.Derived
-#if __GLASGOW_HASKELL__ >= 704
-import Development.Shake.Classes
-#endif
 
 import Development.Shake.Directory
 import Development.Shake.File
diff --git a/Development/Shake/Classes.hs b/Development/Shake/Classes.hs
--- a/Development/Shake/Classes.hs
+++ b/Development/Shake/Classes.hs
@@ -1,30 +1,12 @@
 {-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ >= 704
-{-# LANGUAGE ConstraintKinds #-}
-#endif
 
 -- | This module reexports the six necessary type classes that every 'Rule' type must support.
 --   You can use this module to define new rules without depending on the @binary@, @deepseq@ and @hashable@ packages.
 module Development.Shake.Classes(
-#if __GLASGOW_HASKELL__ >= 704
-    ShakeValue,
-#endif
-    Show,Typeable,Eq,Hashable,Binary,NFData
+    Show(..), Typeable(..), Eq(..), Hashable(..), Binary(..), NFData(..)
     ) where
 
 import Data.Hashable
 import Data.Typeable
 import Data.Binary
 import Control.DeepSeq
-
-
-#if __GLASGOW_HASKELL__ >= 704
--- | Define an alias for the six type classes required for things involved in Shake 'Development.Shake.Rule's.
---   This alias is only available in GHC 7.4 and above, and requires the @ConstraintKinds@ extension.
---
---   To define your own values meeting the necessary constraints it is convenient to use the extensions
---   @GeneralizedNewtypeDeriving@ and @DeriveDataTypeable@ to write:
---
--- > newtype MyType = MyType (String, Bool) deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
-type ShakeValue a = (Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a)
-#endif
diff --git a/Development/Shake/Core.hs b/Development/Shake/Core.hs
--- a/Development/Shake/Core.hs
+++ b/Development/Shake/Core.hs
@@ -8,17 +8,19 @@
 
 module Development.Shake.Core(
     run,
+#if __GLASGOW_HASKELL__ >= 704
+    ShakeValue,
+#endif
     Rule(..), Rules, defaultRule, rule, action, withoutActions,
     Action, apply, apply1, traced,
     getVerbosity, putLoud, putNormal, putQuiet,
     Resource, newResource, withResource
     ) where
 
-import Control.DeepSeq
 import Control.Exception as E
 import Control.Monad
 import Control.Monad.IO.Class
-import Control.Monad.Trans.State
+import Control.Monad.Trans.State as State
 import Data.Typeable
 import Data.Function
 import Data.List
@@ -39,6 +41,18 @@
 ---------------------------------------------------------------------
 -- RULES
 
+#if __GLASGOW_HASKELL__ >= 704
+-- | Define an alias for the six type classes required for things involved in Shake 'Development.Shake.Rule's.
+--   This alias is only available in GHC 7.4 and above, and requires the @ConstraintKinds@ extension.
+--
+--   To define your own values meeting the necessary constraints it is convenient to use the extensions
+--   @GeneralizedNewtypeDeriving@ and @DeriveDataTypeable@ to write:
+--
+-- > newtype MyType = MyType (String, Bool) deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
+type ShakeValue a = (Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a)
+#endif
+
+
 -- | Define a pair of types that can be used by Shake rules.
 --   To import all the type classes required see "Development.Shake.Classes".
 class (
@@ -315,7 +329,7 @@
 
 applyKeyValue :: [Key] -> Action [Value]
 applyKeyValue ks = Action $ do
-    s <- get
+    s <- State.get
     let exec stack k = try $ wrapStack (showStack (database s) stack) $ do
             evaluate $ rnf k
             let s2 = s{depends=[], stack=stack, discount=0, traces=[]}
@@ -329,7 +343,7 @@
     case res of
         Left err -> throw err
         Right (dur, dep, vs) -> do
-            modify $ \s -> s{discount=discount s + dur, depends=dep : depends s}
+            State.modify $ \s -> s{discount=discount s + dur, depends=dep : depends s}
             return vs
 
 
@@ -344,17 +358,17 @@
 --   (see 'shakeReport').
 traced :: String -> IO a -> Action a
 traced msg act = Action $ do
-    s <- get
+    s <- State.get
     start <- liftIO $ started s
     res <- liftIO act
     stop <- liftIO $ started s
-    modify $ \s -> s{traces = (msg,start,stop):traces s}
+    State.modify $ \s -> s{traces = (msg,start,stop):traces s}
     return res
 
 
 putWhen :: (Verbosity -> Bool) -> String -> Action ()
 putWhen f msg = Action $ do
-    s <- get
+    s <- State.get
     when (f $ verbosity s) $
         liftIO $ output s msg
 
@@ -379,7 +393,7 @@
 -- | Run an action which uses part of a finite resource. For an example see 'Resource'.
 withResource :: Resource -> Int -> Action a -> Action a
 withResource r i act = Action $ do
-    s <- get
+    s <- State.get
     (res,s) <- liftIO $ bracket_
         (do res <- acquireResource r i
             case res of
@@ -391,5 +405,5 @@
         (do releaseResource r i
             logger s $ show r ++ " released " ++ show i)
         (runAction s act)
-    put s
+    State.put s
     return res
diff --git a/Development/Shake/Database.hs b/Development/Shake/Database.hs
--- a/Development/Shake/Database.hs
+++ b/Development/Shake/Database.hs
@@ -11,6 +11,7 @@
     showJSON, checkValid,
     ) where
 
+import Development.Shake.Classes
 import Development.Shake.Binary
 import Development.Shake.Pool
 import Development.Shake.Value
@@ -19,9 +20,6 @@
 import Development.Shake.Types
 import Development.Shake.Intern as Intern
 
-import Control.DeepSeq
-import Data.Hashable
-import Data.Typeable
 import Control.Exception
 import Control.Monad
 import qualified Data.HashSet as Set
diff --git a/Development/Shake/Directory.hs b/Development/Shake/Directory.hs
--- a/Development/Shake/Directory.hs
+++ b/Development/Shake/Directory.hs
@@ -6,16 +6,14 @@
     defaultRuleDirectory
     ) where
 
-import Control.DeepSeq
 import Control.Monad
 import Control.Monad.IO.Class
 import Data.Binary
-import Data.Hashable
 import Data.List
-import Data.Typeable
 import qualified System.Directory as IO
 
 import Development.Shake.Core
+import Development.Shake.Classes
 import Development.Shake.FilePath
 import Development.Shake.FilePattern
 
diff --git a/Development/Shake/File.hs b/Development/Shake/File.hs
--- a/Development/Shake/File.hs
+++ b/Development/Shake/File.hs
@@ -6,15 +6,12 @@
     (*>), (**>), (?>)
     ) where
 
-import Control.DeepSeq
 import Control.Monad.IO.Class
-import Data.Binary
-import Data.Hashable
-import Data.Typeable
 import System.Directory
 import qualified Data.ByteString.Char8 as BS
 
 import Development.Shake.Core
+import Development.Shake.Classes
 import Development.Shake.FilePath
 import Development.Shake.FilePattern
 import Development.Shake.FileTime
@@ -119,7 +116,7 @@
 --
 --   This program will build @Main.exe@, given sufficient rules.
 want :: [FilePath] -> Rules ()
-want xs = action $ need xs
+want = action . need
 
 
 root :: String -> (FilePath -> Bool) -> (FilePath -> Action ()) -> Rules ()
diff --git a/Development/Shake/FileTime.hs b/Development/Shake/FileTime.hs
--- a/Development/Shake/FileTime.hs
+++ b/Development/Shake/FileTime.hs
@@ -6,10 +6,7 @@
     getModTimeError, getModTimeMaybe
     ) where
 
-import Control.DeepSeq
-import Data.Binary
-import Data.Hashable
-import Data.Typeable
+import Development.Shake.Classes
 import Data.Int
 import qualified Data.ByteString.Char8 as BS
 
diff --git a/Development/Shake/Files.hs b/Development/Shake/Files.hs
--- a/Development/Shake/Files.hs
+++ b/Development/Shake/Files.hs
@@ -4,16 +4,13 @@
     (?>>), (*>>)
     ) where
 
-import Control.DeepSeq
 import Control.Monad
 import Control.Monad.IO.Class
-import Data.Binary
-import Data.Hashable
 import Data.Maybe
-import Data.Typeable
 import qualified Data.ByteString.Char8 as BS
 
 import Development.Shake.Core
+import Development.Shake.Classes
 import Development.Shake.File
 import Development.Shake.FilePattern
 import Development.Shake.FileTime
diff --git a/Development/Shake/Intern.hs b/Development/Shake/Intern.hs
--- a/Development/Shake/Intern.hs
+++ b/Development/Shake/Intern.hs
@@ -5,10 +5,9 @@
     empty, insert, add, lookup, toList, fromList
     ) where
 
-import Control.DeepSeq
 import Development.Shake.Binary
+import Development.Shake.Classes
 import Prelude hiding (lookup)
-import Data.Hashable
 import qualified Data.HashMap.Strict as Map
 
 
diff --git a/Development/Shake/Oracle.hs b/Development/Shake/Oracle.hs
--- a/Development/Shake/Oracle.hs
+++ b/Development/Shake/Oracle.hs
@@ -36,18 +36,19 @@
 --
 -- @
 -- newtype GhcVersion = GhcVersion () deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
--- 'addOracle' $ \GhcVersion -> return \"7.2.1\"
+-- 'addOracle' $ \\(GhcVersion _) -> return \"7.2.1\"
 -- @
 --
---   If a rule depends on the GHC version, it can then use @'askOracle' GhcVersion@, and
+--   If a rule depends on the GHC version, it can use @'askOracle' (GhcVersion ())@, and
 --   if the GHC version changes, the rule will rebuild. We use a @newtype@ around @()@ to
 --   allow the use of @GeneralizedNewtypeDeriving@. It is common for the value returned
 --   by 'askOracle' to be ignored, in which case 'askOracleWith' may help avoid ambiguous type
 --   messages -- although a wrapper function with an explicit type is encouraged.
+--   The result of 'addOracle' is simply 'askOracle' restricted to the specific type of the added oracle.
 --   To import all the type classes required see "Development.Shake.Classes".
 --
---   We require that each type of @question@ map to exactly one type of @answer@,
---   otherwise a runtime error will be raised.
+--   We require that each call to 'addOracle' uses a different type of @question@ from any
+--   other calls in a given set of 'Rule's, otherwise a runtime error will be raised.
 --
 --   Actions passed to 'addOracle' will be run in every build they are required,
 --   but if their value does not change they will not invalidate any rules depending on them.
@@ -60,15 +61,13 @@
 --newtype GhcPkgVersion = GhcPkgVersion String deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
 --
 --do
---    'addOracle' $ \\GhcPkgList{} -> do
+--    getPkgList <- 'addOracle' $ \\GhcPkgList{} -> do
 --        (out,_) <- 'systemOutput' \"ghc-pkg\" [\"list\",\"--simple-output\"]
 --        return [(reverse b, reverse a) | x <- words out, let (a,_:b) = break (== \'-\') $ reverse x]
---    let getPkgList = 'askOracleWith' (GhcPkgList ()) [(\"\",\"\")] 
 --    --
---    'addOracle' $ \\(GhcPkgVersion pkg) -> do
+--    getPkgVersion <- 'addOracle' $ \\(GhcPkgVersion pkg) -> do
 --        pkgs <- getPkgList
 --        return $ lookup pkg pkgs
---    let getPkgVersion pkg = 'askOracleWith' (GhcPkgVersion pkg) (Just \"\")
 -- @
 --
 --   Using these definitions, any rule depending on the version of @shake@
@@ -80,8 +79,10 @@
     Show q, Typeable q, Eq q, Hashable q, Binary q, NFData q,
     Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a
 #endif
-    ) => (q -> Action a) -> Rules ()
-addOracle act = rule $ \(OracleQ q) -> Just $ fmap OracleA $ act q
+    ) => (q -> Action a) -> Rules (q -> Action a)
+addOracle act = do
+    rule $ \(OracleQ q) -> Just $ fmap OracleA $ act q
+    return askOracle
 
 
 -- | Get information previously added with 'addOracle', the @question@/@answer@ types must match those provided
diff --git a/Development/Shake/Rerun.hs b/Development/Shake/Rerun.hs
--- a/Development/Shake/Rerun.hs
+++ b/Development/Shake/Rerun.hs
@@ -4,12 +4,8 @@
     defaultRuleRerun, alwaysRerun
     ) where
 
-import Control.DeepSeq
-import Data.Binary
-import Data.Hashable
-import Data.Typeable
-
 import Development.Shake.Core
+import Development.Shake.Classes
 
 
 newtype AlwaysRerunQ = AlwaysRerunQ ()
diff --git a/Development/Shake/Storage.hs b/Development/Shake/Storage.hs
--- a/Development/Shake/Storage.hs
+++ b/Development/Shake/Storage.hs
@@ -13,14 +13,13 @@
 import Development.Shake.Locks
 
 import Control.Arrow
-import Control.DeepSeq
 import Control.Exception as E
 import Control.Monad
 import Control.Concurrent
 import Data.Binary.Get
 import Data.Binary.Put
 import Data.Char
-import Data.Hashable
+import Development.Shake.Classes
 import qualified Data.HashMap.Strict as Map
 import Data.List
 import System.Directory
diff --git a/Development/Shake/Value.hs b/Development/Shake/Value.hs
--- a/Development/Shake/Value.hs
+++ b/Development/Shake/Value.hs
@@ -10,8 +10,7 @@
     ) where
 
 import Development.Shake.Binary
-import Control.DeepSeq
-import Data.Hashable
+import Development.Shake.Classes
 import Data.Typeable
 
 import Data.Bits
diff --git a/Examples/Self/Main.hs b/Examples/Self/Main.hs
--- a/Examples/Self/Main.hs
+++ b/Examples/Self/Main.hs
@@ -24,10 +24,18 @@
     -- fixup to cope with Cabal's generated files
     let fixPaths x = if x == "Paths_shake.hs" then "Paths.hs" else x
 
+    ghcPkg <- addOracle $ \GhcPkg{} -> do
+        (out,_) <- systemOutput "ghc-pkg" ["list","--simple-output"]
+        return $ words out
+
+    ghcFlags <- addOracle $ \GhcFlags{} -> do
+        pkgs <- readFileLines $ obj ".pkgs"
+        return $ map ("-package=" ++) pkgs
+
     let ghc args = do
             -- since ghc-pkg includes the ghc package, it changes if the version does
-            askOracleWith (GhcPkg ()) [""]
-            flags <- askOracle $ GhcFlags ()
+            ghcPkg $ GhcPkg ()
+            flags <- ghcFlags $ GhcFlags ()
             system' "ghc" $ args ++ flags
 
     obj "/*.exe" *> \out -> do
@@ -61,14 +69,6 @@
     obj ".pkgs" *> \out -> do
         src <- readFile' "shake.cabal"
         writeFileLines out $ sort $ cabalBuildDepends src
-
-    addOracle $ \GhcPkg{} -> do
-        (out,_) <- systemOutput "ghc-pkg" ["list","--simple-output"]
-        return $ words out
-
-    addOracle $ \GhcFlags{} -> do
-        pkgs <- readFileLines $ obj ".pkgs"
-        return $ map ("-package=" ++) pkgs
 
 
 ---------------------------------------------------------------------
diff --git a/shake.cabal b/shake.cabal
--- a/shake.cabal
+++ b/shake.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.8
 build-type:         Simple
 name:               shake
-version:            0.5
+version:            0.6
 license:            BSD3
 license-file:       LICENSE
 category:           Development
