diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
 # apecs
+##### [hackage](https://hackage.haskell.org/package/apecs) | [documentation](https://hackage.haskell.org/package/apecs-0.2.0.2/docs/Apecs.html) | [tutorial](https://github.com/jonascarpay/apecs/blob/master/tutorials/RTS.md)
 
 apecs is an Entity Component System inspired by [specs](https://github.com/slide-rs/specs) and [Entitas](https://github.com/sschmid/Entitas-CSharp).
 It exposes a DSL that translates to fast storage operations, resulting in expressivity without sacrificing performance or safety.
diff --git a/apecs.cabal b/apecs.cabal
--- a/apecs.cabal
+++ b/apecs.cabal
@@ -1,5 +1,5 @@
 name:                apecs
-version:             0.2.0.2
+version:             0.2.0.3
 homepage:            https://github.com/jonascarpay/apecs#readme
 license:             BSD3
 license-file:        LICENSE
@@ -34,34 +34,19 @@
     -Odph
     -fno-warn-unused-top-binds
 
-executable simple
-  hs-source-dirs:
-    example
+test-suite apecs-spec
+  type:
+    exitcode-stdio-1.0
   main-is:
-    Simple.hs
-  build-depends:
-    base, apecs, linear
-  default-language:
-    Haskell2010
-  ghc-options:
-    -fno-warn-unused-top-binds
-
-executable rts
+    Spec.hs
   hs-source-dirs:
-    example
-  main-is:
-    RTS.hs
+    spec
   build-depends:
-    base,
+    base >= 4.7 && < 5,
     apecs,
-    sdl2,
-    random,
-    linear
+    QuickCheck
   default-language:
     Haskell2010
-  ghc-options:
-    -Odph
-    -fno-warn-unused-top-binds
 
 benchmark apecs-bench
   type:
@@ -71,7 +56,10 @@
   main-is:
     Main.hs
   build-depends:
-    base, apecs, criterion, linear
+    base >= 4.7 && < 5,
+    apecs,
+    criterion,
+    linear
   default-language:
     Haskell2010
   ghc-options:
@@ -81,4 +69,3 @@
     -optlo-O3
     -funfolding-use-threshold1000
     -funfolding-keeness-factor1000
-    -threaded
diff --git a/example/RTS.hs b/example/RTS.hs
deleted file mode 100644
--- a/example/RTS.hs
+++ /dev/null
@@ -1,159 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, TypeOperators #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE DataKinds #-}
-
-module Main where
-
-import Control.Monad as M
-import qualified SDL
-import SDL (($=))
-import System.Random
-import Data.Proxy
-import SDL.Vect
-
-import Apecs as A
-import Apecs.Stores
-import Apecs.Util
-
-hres, vres :: Num a => a
-hres = 1024
-vres = 768
-
-newtype Position = Position {getPos :: V2 Double} deriving (Show, Num)
-instance Component Position where
-  type Storage Position = Map Position
-
-newtype Target = Target (V2 Double)
-instance Component Target where
-  type Storage Target = Map Target
-
-data Selected = Selected
-instance Flag Selected where flag = Selected
-instance Component Selected where
-  type Storage Selected = Set Selected
-
-data MouseState = Dragging !(V2 Double) !(V2 Double) | Rest
-instance Component MouseState where
-  type Storage MouseState = Global MouseState
-
-data World = World
-  { positions     :: Storage Position
-  , targets       :: Storage Target
-  , selected      :: Storage Selected
-  , mouseState    :: Storage MouseState
-  , entityCounter :: Storage EntityCounter
-  }
-instance World `Has` Position      where getStore = System $ asks positions
-instance World `Has` Target        where getStore = System $ asks targets
-instance World `Has` Selected      where getStore = System $ asks selected
-instance World `Has` MouseState    where getStore = System $ asks mouseState
-instance World `Has` EntityCounter where getStore = System $ asks entityCounter
-
-type System' a = System World a
-
-game :: System' ()
-game = do
-  (window, renderer) <- initRenderer
-
-  -- Add units
-  replicateM_ 5000 $ do
-    x <- liftIO$ randomRIO (100,hres/2)
-    y <- liftIO$ randomRIO (100,vres-100)
-    newEntity (Position (V2 x y))
-
-  let loop = do
-        shouldQuit <- handleEvents
-        step
-        render renderer
-        unless shouldQuit loop
-
-  loop
-
-  cleanup (window, renderer)
-
-render :: SDL.Renderer -> System' ()
-render renderer = do
-  liftIO$ SDL.rendererDrawColor renderer $= V4 0 0 0 255
-  liftIO$ SDL.clear renderer
-
-  cimapM_ $ \(e, Position p) -> do
-    e <- exists (cast e :: Entity Selected)
-    liftIO$ SDL.rendererDrawColor renderer $= if e then V4 255 255 255 255 else V4 255 0 0 255
-    SDL.drawPoint renderer (P (round <$> p))
-
-  liftIO$ SDL.rendererDrawColor renderer $= V4 255 255 255 255
-  r <- readGlobal
-  case r of
-    Dragging a b -> SDL.drawRect renderer (Just $ SDL.Rectangle (P (round <$> a)) (round <$> b-a))
-    _ -> return ()
-
-  SDL.present renderer
-
-step = do
-  let speed :: Num a => a
-      speed = 5
-      stepPosition :: (Target, Position) -> Safe (Target, Position)
-      stepPosition (Target t, Position p)
-        | norm (p-t) < speed = Safe (Nothing, Just (Position t))
-        | otherwise               = Safe (Just (Target t), Just (Position (p + speed * normalize (t-p))))
-
-  cmap' stepPosition
-
-  m <- readGlobal
-  case m of
-    Rest -> return ()
-    Dragging (V2 ax ay) (V2 bx by) -> do
-      resetStore (Proxy :: Proxy Selected)
-      let f :: Position -> Safe Selected
-          f (Position (V2 x y)) = Safe (x >= min ax bx && x <= max ax bx && y >= min ay by && y <= max ay by)
-      rmap' f
-
-handleEvents = do
-  events <- fmap SDL.eventPayload <$> SDL.pollEvents
-  mapM_ handleEvent events
-  return (SDL.QuitEvent `elem` events)
-  where
-    handleEvent :: SDL.EventPayload -> System' ()
-    handleEvent (SDL.MouseButtonEvent (SDL.MouseButtonEventData _ SDL.Pressed _ SDL.ButtonLeft _ (P p))) =
-      let p' = fromIntegral <$> p in writeGlobal (Dragging p' p')
-
-    handleEvent (SDL.MouseButtonEvent (SDL.MouseButtonEventData _ SDL.Released _ SDL.ButtonLeft _ _)) =
-      writeGlobal Rest
-
-    handleEvent (SDL.MouseMotionEvent (SDL.MouseMotionEventData _ _ _ (P p) _)) = do
-      md <- readGlobal
-      case md of
-        Rest -> return ()
-        Dragging a _ -> writeGlobal (Dragging a (fromIntegral <$> p))
-
-    handleEvent (SDL.MouseButtonEvent (SDL.MouseButtonEventData _ SDL.Pressed _ SDL.ButtonRight _ (P (V2 px py)))) = do
-      sl :: Slice Selected <- slice All
-      let r = (*3) . subtract 1 . sqrt . fromIntegral$ sliceSize sl
-
-      sliceForM_ sl $ \e -> do
-        dx <- liftIO$ randomRIO (-r,r)
-        dy <- liftIO$ randomRIO (-r,r)
-        set e (Target (V2 (fromIntegral px+dx) (fromIntegral py+dy)))
-
-    handleEvent _ = return ()
-
-initRenderer = liftIO$ do
-  SDL.initialize [SDL.InitVideo]
-  SDL.HintRenderScaleQuality $= SDL.ScaleLinear
-  window <- SDL.createWindow "Apecs tutorial" SDL.defaultWindow {SDL.windowInitialSize = V2 hres vres}
-  SDL.showWindow window
-  renderer <- SDL.createRenderer window (-1) (SDL.RendererConfig SDL.AcceleratedRenderer False)
-  return (window, renderer)
-
-cleanup (window, renderer) = liftIO$ do
-  SDL.destroyRenderer renderer
-  SDL.destroyWindow window
-  SDL.quit
-
-main :: IO ()
-main = do
-  w <- World <$> initStore <*> initStore <*> initStore <*> initStoreWith Rest <*> initCounter
-  runSystem game w
diff --git a/example/Simple.hs b/example/Simple.hs
deleted file mode 100644
--- a/example/Simple.hs
+++ /dev/null
@@ -1,63 +0,0 @@
-{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies, MultiParamTypeClasses, TypeOperators #-}
-
-import Apecs
-import Apecs.Stores
-import Apecs.Util
-import Linear
-
--- Component data definitions
-newtype Velocity = Velocity (V2 Double) deriving (Eq, Show)
-newtype Position = Position (V2 Double) deriving (Eq, Show)
-data Enemy = Enemy -- A single constructor for tagging entites as enemies
-
--- Define Velocity as a component by giving it a storage type
-instance Component Velocity where
-  -- Store velocities in a cached map
-  type Storage Velocity = Cache 100 (Map Velocity)
-
-instance Component Position where
-  type Storage Position = Cache 100 (Map Position)
-
-instance Flag Enemy where flag = Enemy
-instance Component Enemy where
-  -- Because enemy is just a flag, we can use a set
-  type Storage Enemy = Set Enemy
-
--- Define your world as containing the storages of your components
-data World = World
-  { positions     :: Storage Position
-  , velocities    :: Storage Velocity
-  , enemies       :: Storage Enemy
-  , entityCounter :: Storage EntityCounter }
-
--- Define Has instances for components to allow type-driven access to their storages
-instance World `Has` Position      where getStore = System $ asks positions
-instance World `Has` Velocity      where getStore = System $ asks velocities
-instance World `Has` Enemy         where getStore = System $ asks enemies
-instance World `Has` EntityCounter where getStore = System $ asks entityCounter
-
-type System' a = System World a
-
-game :: System' ()
-game = do
-  -- Create new entities
-  ety <- newEntity (Position 0)
-  -- Components can be composed using tuples
-  newEntity (Position 0, Velocity 1)
-  -- Tagging one as an enemy is a matter of adding the constructor
-  newEntity (Position 1, Velocity 1, Enemy)
-
-  -- Side effects
-  liftIO$ putStrLn "Stepping velocities"
-  -- rmap maps a pure function over all entities in its domain
-  rmap $ \(Position p, Velocity v) -> Position (v+p)
-
-  -- Set can be used to (over)write components
-  set ety (Position 2, Enemy)
-
-  -- Print the positions of all enemies
-  cmapM_ $ \(Enemy, Position p) -> liftIO (print p)
-
-main :: IO ()
-main = do w <- World <$> initStore <*> initStore <*> initStore <*> initCounter
-          runSystem game w
diff --git a/spec/Spec.hs b/spec/Spec.hs
new file mode 100644
--- /dev/null
+++ b/spec/Spec.hs
@@ -0,0 +1,108 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+import Test.QuickCheck
+import Test.QuickCheck.Monadic
+import Control.Monad
+
+import Apecs
+import Apecs.Types
+import Apecs.Util
+import qualified Apecs.Stores as S
+
+type Vec = (Double, Double)
+
+newtype Position = Position Vec deriving (Arbitrary, Eq, Show)
+instance Component Position where
+  type Storage Position = S.Map Position
+
+newtype CachePos = CachePos Vec deriving (Arbitrary, Eq, Show)
+instance Component CachePos where
+  type Storage CachePos = S.Map CachePos
+
+
+newtype Velocity = Velocity Vec deriving (Arbitrary, Eq, Show)
+instance Component Velocity where
+  type Storage Velocity = S.Map Velocity
+
+
+data Flag = Flag
+instance Arbitrary Flag where arbitrary = return Flag
+instance S.Flag Flag where flag = Flag
+instance Component Flag where
+  type Storage Flag = S.Set Flag
+
+
+newtype RandomEntity a = RandomEntity (Entity a) deriving (Eq, Show)
+instance Arbitrary (RandomEntity a) where
+  arbitrary = RandomEntity . Entity <$> arbitrary
+
+newtype W1 c = W1 {getIdentity :: (Storage c)}
+instance Component c => Has (W1 c) c where getStore = System $ asks getIdentity
+
+data W2 a b = W2 { c1 :: Storage a
+                 , c2 :: Storage b
+                 }
+
+instance (Component a, Component b) => Has (W2 a b) a where getStore = System $ asks c1
+instance (Component a, Component b) => Has (W2 a b) b where getStore = System $ asks c2
+
+getSetPos :: [(RandomEntity Position, Position)] -> RandomEntity Position -> Position -> Property
+getSetPos cs (RandomEntity e) p = monadicIO $ run f >>= assert
+  where
+    f = do
+      w :: Storage Position <- initStore
+      runWith (W1 w) $ do
+        forM_ cs $ \(RandomEntity ety, pos) -> set ety pos
+        set e p
+        Safe r <- get e
+        return (r == Just p)
+
+getSetCPos :: [(RandomEntity CachePos, CachePos)] -> RandomEntity CachePos -> CachePos -> Property
+getSetCPos cs (RandomEntity e) p = monadicIO $ run f >>= assert
+  where
+    f = do
+      w :: Storage CachePos <- initStore
+      runWith (W1 w) $ do
+        forM_ cs $ \(RandomEntity ety, pos) -> set ety pos
+        set e p
+        Safe r <- get e
+        return (r == Just p)
+
+getSetVCPos :: [(RandomEntity (Velocity, CachePos), (Velocity, CachePos))] -> RandomEntity (Velocity, CachePos) -> (Velocity, CachePos) -> Property
+getSetVCPos cs (RandomEntity e) (v,p) = monadicIO $ run f >>= assert
+  where
+    f = do
+      wp :: Storage CachePos <- initStore
+      wv :: Storage Velocity <- initStore
+      runWith (W2 wp wv) $ do
+        forM_ cs $ \(RandomEntity ety, pos) -> set ety pos
+        set e (v,p)
+        Safe r <- get e
+        return (r == (Just v, Just p))
+
+cmapVP :: [(RandomEntity (Velocity, CachePos), (Velocity, CachePos))] -> RandomEntity (Velocity, CachePos) -> (Velocity, CachePos) -> Property
+cmapVP cs (RandomEntity e) (v,p) = monadicIO $ run f >>= assert
+  where
+    f = do
+      let swapP (CachePos (x,y)) = CachePos (y,x)
+          swapV (Velocity (x,y)) = Velocity (y,x)
+      wp :: Storage CachePos <- initStore
+      wv :: Storage Velocity <- initStore
+      runWith (W2 wp wv) $ do
+        forM_ cs $ \(RandomEntity ety, pos) -> set ety pos
+        set e (v,p)
+        cmap $ \(v,p) -> (swapV v, swapP p)
+        Safe r <- get e
+        return (r == (Just $ swapV v, Just $ swapP p))
+
+
+main = do
+  quickCheck getSetPos
+  quickCheck getSetCPos
+  quickCheck getSetVCPos
+  quickCheck cmapVP
diff --git a/src/Apecs/Stores.hs b/src/Apecs/Stores.hs
--- a/src/Apecs/Stores.hs
+++ b/src/Apecs/Stores.hs
@@ -20,8 +20,7 @@
 import qualified Data.Vector.Unboxed as U
 import qualified Data.Vector.Unboxed.Mutable as UM
 import qualified Data.Vector.Mutable as VM
-import Control.Monad
-import Control.Monad.IO.Class
+import Control.Monad.Reader
 import GHC.TypeLits
 import Data.Proxy
 
diff --git a/src/Apecs/System.hs b/src/Apecs/System.hs
--- a/src/Apecs/System.hs
+++ b/src/Apecs/System.hs
@@ -57,7 +57,7 @@
 
 -- | Writes a component to a given entity. Will overwrite existing components.
 {-# INLINE set #-}
-set :: forall w c e. (Store (Storage c), Stores (Storage c) ~ c, Has w c) => Entity e -> c -> System w ()
+set :: forall w c e. (IsRuntime c, Has w c) => Entity e -> c -> System w ()
 set (Entity ety) x = do
   s :: Storage c <- getStore
   liftIO$ explSet s ety x
diff --git a/src/Apecs/Types.hs b/src/Apecs/Types.hs
--- a/src/Apecs/Types.hs
+++ b/src/Apecs/Types.hs
@@ -30,7 +30,6 @@
 class Component c => Has w c where
   getStore :: System w (Storage c)
 
-
 -- Storage types
 -- | Common for every storage. Represents a container that can be initialized.
 class Initializable s where
@@ -126,7 +125,9 @@
       sys (ety,x)
 
 -- | A constraint that indicates that the runtime representation of @c@ is @c@
+--   This will almost always be the case, but it _might_ not be so we need this constraint.
 type IsRuntime c = (Store (Storage c), Stores (Storage c) ~ c)
+
 -- | Class of storages for global values
 class GlobalRW s c where
   {-# MINIMAL explGlobalRead, explGlobalWrite #-}
diff --git a/tutorials/RTS.md b/tutorials/RTS.md
--- a/tutorials/RTS.md
+++ b/tutorials/RTS.md
@@ -5,7 +5,7 @@
 We'll be using [SDL2](https://github.com/haskell-game/sdl2) for graphics.
 Don't worry if you don't know SDL2, neither do I.
 We'll only be drawing single pixels to the screen, so it should be pretty easy to follow what's going on.
-The final result can be found [here](https://github.com/jonascarpay/apecs/blob/master/example/RTS.hs).
+The final result can be found [here](https://github.com/jonascarpay/apecs/blob/master/examples/RTS.hs).
 You can run it with `stack build && stack exec rts`.
 I will be skipping some details, so make sure to keep it handy if you want to follow along.
 
@@ -279,7 +279,7 @@
 #### Conclusion
 These are the tools you need to build a game in apecs.
 I did not discuss every line in the final program, as they were mostly SDL-related.
-Again, the final version in its full glory can be found [here](https://github.com/jonascarpay/apecs/blob/master/example/RTS.hs).
+Again, the final version in its full glory can be found [here](https://github.com/jonascarpay/apecs/blob/master/examples/RTS.hs).
 
 The reason for writing this tutorial at this point is that apecs is now sufficiently developed where it has most of the functionality of other ECS, and is now a viable way of developing games in Haskell.
 The library is still under development, but for now, that is mostly on parts outside the scope of this tutorial.
