diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
 # servant-ede
 
-Support ede templates in servant. See the documentation of the `Servant.HTML.EDE` module for examples and explanations.
+Support ede templates in servant. See the documentation of the `Servant.EDE` module for examples and explanations, [on hackage](http://hackage.haskell.org/package/servant-ede).
diff --git a/example/example.hs b/example/example.hs
--- a/example/example.hs
+++ b/example/example.hs
@@ -5,29 +5,60 @@
 import Control.Monad
 import Data.Monoid
 import GHC.Generics
+import Network.HTTP.Media ((//))
 import Network.Wai.Handler.Warp
 import Servant
-import Servant.HTML.EDE
-import Text.EDE
+import Servant.EDE
 
+-- * Using 'Tpl' for rendering CSS templates
+
+data CSS
+
+instance Accept CSS where
+  contentType _ = "text" // "css"
+
+type StyleAPI = "style.css" :> Get '[Tpl CSS "style.tpl"] CSSData
+
+data CSSData = CSSData
+  { darken :: Bool
+  , pageWidth :: Int
+  } deriving Generic
+
+instance ToObject CSSData
+
+styleServer :: Server StyleAPI
+styleServer = -- FOR NOW
+  return (CSSData True 400)
+
+-- * Using 'HTML' for HTML template rendering
+
 data User = User { name :: String, age :: Int }
   deriving (Eq, Show, Generic)
 
 instance ToObject User where
 
-type API = "index" :> Tpl "index.tpl"
-      :<|> "foo"   :> Tpl "foo.tpl"
-      :<|> "user"  :> Get '[HTML "user.tpl"] User
+type UserAPI = "user" :> Get '[HTML "user.tpl"] User
 
-api :: Proxy API
-api = Proxy
+userServer :: Server UserAPI
+userServer = return (User "lambdabot" 35)
 
-server :: Server API
-server = rawTemplate :<|> rawTemplate :<|> return (User "lambdabot" 35)
+type API = StyleAPI :<|> UserAPI
 
-  where rawTemplate = return mempty
+api :: Proxy API
+api = Proxy
 
 main :: IO ()
 main = do
   loadTemplates api "example"
-  run 8082 (serve api server)
+  run 8082 (serve api $ styleServer :<|> userServer)
+
+-- You can now head to:
+-- http://localhost:8082/user
+-- and
+-- http://localhost:8082/style.css
+-- to see 'HTML' and 'Tpl' + 'CSS' in action,
+-- respectively.
+--
+-- Feel free to tweak the content of the template files
+-- as well as the 'User' and 'CSSData' values in this program
+-- to see how it affects the rendering.
diff --git a/servant-ede.cabal b/servant-ede.cabal
--- a/servant-ede.cabal
+++ b/servant-ede.cabal
@@ -1,14 +1,12 @@
--- Initial servant-ede.cabal generated by cabal init.  For further 
--- documentation, see http://haskell.org/cabal/users-guide/
-
 name:                servant-ede
-version:             0.4.0.1
+version:             0.5
 synopsis:            Combinators for rendering EDE templates in servant web applications
 description:
   Combinators for rendering EDE templates in servant web applications.
   .
-  Documentation and examples available at "Servant.HTML.EDE".
+  Documentation and examples available at "Servant.EDE".
 homepage:            http://github.com/alpmestan/servant-ede
+bug-reports:         http://github.com/alpmestan/servant-ede/issues
 license:             BSD3
 license-file:        LICENSE
 author:              Alp Mestanogullari
@@ -18,32 +16,35 @@
 build-type:          Simple
 extra-source-files:  README.md
 cabal-version:       >=1.10
+source-repository head
+  type: git
+  location: git://github.com/alpmestan/servant-ede.git
 
 library
-  exposed-modules:     Servant.HTML.EDE
-  other-modules:
-      Servant.HTML.EDE.Internal
-    , Servant.HTML.EDE.Internal.Reify
-    , Servant.HTML.EDE.Internal.Templates
-    , Servant.HTML.EDE.Internal.ToObject
-    , Servant.HTML.EDE.Internal.Validate
+  exposed-modules:
+      Servant.EDE
+    , Servant.EDE.Internal
+    , Servant.EDE.Internal.Reify
+    , Servant.EDE.Internal.ToObject
+    , Servant.EDE.Internal.Validate
 
   build-depends:
-      aeson >= 0.8
+      aeson >= 0.8 && <0.10
     , base >=4.7 && <5
-    , bytestring >= 0.10
-    , filepath >= 1.2
-    , ede >= 0.2
-    , either >= 4
-    , http-media >= 0.6
-    , http-types >= 0.8
-    , semigroups >= 0.16
-    , servant >= 0.4
-    , servant-server >= 0.4
-    , text >= 1.0
-    , transformers >= 0.4
-    , unordered-containers >= 0.2
-    , wai >= 3.0
+    , bytestring >= 0.10 && <0.11
+    , filepath >= 1.2 && <1.5
+    , ede >= 0.2 && <0.3
+    , either >= 4.0 && <4.5
+    , http-media >= 0.6 && <0.7
+    , http-types >= 0.8 && <0.9
+    , semigroups >= 0.16 && <0.17
+    , servant >= 0.4 && <0.5
+    , text >= 1.0 && <1.3
+    , transformers >= 0.4 && <0.5
+    , unordered-containers >= 0.2 && <0.3
+    , vector >= 0.9 && <0.11
+    , wai >= 3.0 && <3.1
+    , xss-sanitize >= 0.3 && <0.4
 
   ghc-options:         -O2 -Wall
   hs-source-dirs:      src
@@ -57,6 +58,7 @@
   build-depends:
       base >= 4.7 && <5
     , ede
+    , http-media
     , servant-server
     , servant-ede
     , warp >= 3.0
diff --git a/src/Servant/EDE.hs b/src/Servant/EDE.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/EDE.hs
@@ -0,0 +1,341 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Servant.EDE
+-- Copyright   :  (c) Alp Mestanogullari 2015
+-- Maintainer  :  alpmestan@gmail.com
+-- Stability   :  experimental
+--
+-- Rendering EDE templates with servant.
+--
+-- This package provides two combinators to be used as content-types
+-- with servant (i.e just like 'JSON'), 'HTML' and 'Tpl'.
+--
+-- - 'HTML' takes a filename as parameter and lets you render the template
+--   with that name against the data returned by a request handler using
+--   the @text\/html;charset=utf-8@ MIME type, XSS-sanitizing the said data
+--   along the way. See 'HTML' for an example.
+-- - 'Tpl' does the same except that it's parametrized over the content type
+--   to be sent along with the rendered template. Any type that has an 'Accept'
+--   instance will do. See 'Tpl' for an example.
+-----------------------------------------------------------------------------
+module Servant.EDE
+  ( -- * Combinators
+    HTML
+  , Tpl
+
+    -- * Sending Haskell data to templates
+  , ToObject(..)
+
+  , -- * Loading template files (mandatory)
+    loadTemplates
+  , TemplateFiles
+  , Reify
+  , Templates
+  , Errors
+  , TemplateError
+  ) where
+
+#if __GLASGOW_HASKELL__ < 710
+import Control.Applicative
+import Data.Traversable (traverse)
+#endif
+
+import Control.Concurrent
+import Control.Monad.IO.Class
+import Data.Aeson (Object, Value(..))
+import Data.Foldable (fold)
+import Data.HashMap.Strict (HashMap, (!))
+import Data.Proxy
+import Data.Semigroup
+import Data.Text (Text)
+import Data.Text.Lazy.Encoding (encodeUtf8)
+import GHC.TypeLits
+import Network.HTTP.Media hiding (Accept)
+import Servant.API
+import Servant.EDE.Internal.Reify
+import Servant.EDE.Internal.ToObject
+import Servant.EDE.Internal.Validate
+import System.FilePath
+import System.IO.Unsafe
+import Text.EDE
+import Text.HTML.SanitizeXSS
+
+import qualified Data.HashMap.Strict as HM
+import qualified Data.Vector         as V
+
+-- | This function initializes a global
+--   template store (i.e a 'Templates' value) and fills it with
+--   the resulting compiled templates if all of them are compiled
+--   successfully. If that's not the case, the global template store
+--   (under an 'MVar') is left empty.
+--
+--   /IMPORTANT/: Must /always/ be called before starting your /servant/ application. Example:
+--
+-- > type API = Get '[HTML "home.tpl"] HomeData
+-- >
+-- > api :: Proxy API
+-- > api = Proxy
+-- >
+-- > main :: IO ()
+-- > main = loadTemplates api "path/to/templates" >>= print
+--
+-- This would try to load @home.tpl@, printing any error or
+-- registering the compiled template in a global (but safe)
+-- compiled template store, if successfully compiled.
+loadTemplates :: (Reify (TemplateFiles api), Applicative m, MonadIO m)
+              => Proxy api
+              -> FilePath -- ^ root directory for the templates
+              -> m Errors
+loadTemplates proxy dir = do
+  res <- loadTemplates' proxy dir
+  case res of
+    Left errs  -> return errs
+    Right tpls -> do
+      liftIO $ putMVar __template_store tpls
+      return []
+
+loadTemplates' :: (Reify (TemplateFiles api), Applicative m, MonadIO m)
+               => Proxy api
+               -> FilePath   -- ^ root directory for the templates
+               -> m (Either Errors Templates)
+loadTemplates' proxy templatedir =
+  fmap (eitherValidate . fmap fold) . runValidateT $
+    traverse (processFile templatedir) files
+
+  where files :: [FilePath]
+        files = templateFiles proxy
+
+-- | A generic template combinator, parametrized over
+--   the content-type (or MIME) associated to the template.
+--
+--   The first parameter is the content-type you want to send along with
+--   rendered templates (must be an instance of 'Accept').
+--
+--   The second parameter is the name of (or path to) the template file.
+--   It must live under the 'FilePath' argument of 'loadTemplates'.
+--
+--   Any type used with this content-type (like @CSSData@ below)
+--   must have an instance of the 'ToObject' class. The field names
+--   become the variable names in the template world.
+--
+--   Here is how you could render and serve, say, /CSS/
+--   (Cascading Style Sheets) templates that make use
+--   of some @CSSData@ data type to tweak the styling.
+--
+-- @
+-- data CSS
+--
+-- instance Accept CSS where
+--   contentType _ = "text" // "css"
+--
+-- type StyleAPI = "style.css" :> Get '[Tpl CSS "style.tpl"] CSSData
+--
+-- styleAPI :: Proxy StyleAPI
+-- styleAPI = Proxy
+--
+-- data CSSData = CSSData
+--   { darken :: Bool
+--   , pageWidth :: Int
+--   } deriving Generic
+--
+-- instance ToObject CSSData
+--
+-- server :: Server API
+-- server = -- produce a CSSData value depending on whatever is relevant...
+--
+-- main :: IO ()
+-- main = do
+--   loadTemplates styleAPI "./templates"
+--   run 8082 (serve styleAPI server)
+-- @
+--
+-- This will look for a template at @.\/templates\/style.tpl@,
+-- which could for example be:
+--
+-- > body {
+-- >   {% if darken %}
+-- >   background-color: #222222;
+-- >   color: blue;
+-- >   {% else %}
+-- >   background-color: white;
+-- >   color: back;
+-- >   {% endif %}
+-- > }
+-- >
+-- > #content {
+-- >   width: {{ pageWidth }};
+-- >   margin: 0 auto;
+-- > }
+--
+-- A complete, runnable version of this can be found
+-- in the @examples@ folder of the git repository.
+data Tpl (ct :: *) (file :: Symbol)
+
+-- the filename doesn't matter for the content type,
+-- as long as 'ct' is a valid one (html, json, css, etc or application-specific)
+instance Accept ct => Accept (Tpl ct file) where
+  contentType _ = contentType ctproxy
+    where ctproxy = Proxy :: Proxy ct
+
+instance (KnownSymbol file, Accept ct, ToObject a) => MimeRender (Tpl ct file) a where
+  mimeRender _ val = encodeUtf8 . result (error . show) id $
+    render templ (toObject val)
+
+    where templ = tmap ! filename
+          filename = symbolVal (Proxy :: Proxy file)
+          tmap = templateMap $ unsafePerformIO (readMVar __template_store)
+
+__template_store :: MVar Templates
+__template_store = unsafePerformIO newEmptyMVar
+
+-- | 'HTML' content type, but more than just that.
+--
+--   'HTML' takes a type-level string which is
+--   a filename for the template you want to use to
+--   render values. Just like 'Tpl', types used with
+--   the 'HTML' content type (like @User@ below)
+--   must provide a 'ToObject' instance.
+--
+--   Example:
+--
+-- @
+-- type UserAPI = "user" :> Get '[JSON, HTML "user.tpl"] User
+--
+-- userAPI :: Proxy UserAPI
+-- userAPI = Proxy
+--
+-- data User = User { name :: String, age :: Int } deriving Generic
+--
+-- instance ToObject User
+--
+-- server :: Server API
+-- server = return (User "lambdabot" 31)
+--
+-- main :: IO ()
+-- main = do
+--   loadTemplates userAPI "./templates"
+--   run 8082 (serve userAPI server)
+-- @
+--
+-- This will look for a template at @.\/templates\/user.tpl@, which could
+-- for example be:
+--
+-- > <ul>
+-- >   <li><strong>Name:</strong> {{ name }}</li>
+-- >   <li><strong>Age:</strong> {{ age }}</li>
+-- > </ul>
+--
+-- /IMPORTANT/: it XSS-sanitizes every bit of text in the 'Object'
+-- passed to the template.
+data HTML (file :: Symbol)
+
+-- | @text/html;charset=utf-8@
+instance Accept (HTML file) where
+  contentType _ = "text" // "html" /: ("charset", "utf-8")
+
+-- | XSS-sanitizes data before rendering it
+instance (KnownSymbol file, ToObject a) => MimeRender (HTML file) a where
+  mimeRender _ val = mimeRender (Proxy :: Proxy (Tpl (HTML file) file)) $
+    sanitizeObject (toObject val)
+
+sanitizeObject :: Object -> Object
+sanitizeObject = HM.fromList . map sanitizeKV . HM.toList
+
+sanitizeKV :: (Text, Value) -> (Text, Value)
+sanitizeKV (k, v) = (sanitize k, sanitizeValue v)
+
+sanitizeValue :: Value -> Value
+sanitizeValue (String s) = String (sanitize s)
+sanitizeValue (Array a) = Array (V.map sanitizeValue a)
+sanitizeValue (Object o) = Object (sanitizeObject o)
+sanitizeValue x = x
+
+type family Append (xs :: [k]) (ys :: [k]) :: [k] where
+  Append '[]       ys = ys
+  Append (x ': xs) ys = x ': Append xs ys
+
+type family Member (x :: k) (xs :: [k]) :: Bool where
+  Member x (x ': xs) = 'True
+  Member x (y ': xs) = Member x xs
+  Member x       '[] = 'False
+
+-- | Collect all the template filenames of an API as a type-level
+--   list of strings, by simply looking at all occurences of the
+--   'Tpl' and 'HTML' combinators and keeping the filenames associated to them.
+type family TemplateFiles (api :: k) :: [Symbol]
+type instance TemplateFiles (a :<|> b)    = Append (TemplateFiles a) (TemplateFiles b)
+type instance TemplateFiles (a :> r)      = TemplateFiles r
+type instance TemplateFiles (Delete cs a) = CTFiles cs
+type instance TemplateFiles (Get cs a)    = CTFiles cs
+type instance TemplateFiles (Patch cs a)  = CTFiles cs
+type instance TemplateFiles (Post cs a)   = CTFiles cs
+type instance TemplateFiles (Put cs a)    = CTFiles cs
+type instance TemplateFiles Raw           = '[]
+
+type family CTFiles (cts :: [*]) :: [Symbol] where
+  CTFiles '[]        = '[]
+  CTFiles (c ': cts) = Append (CTFile c) (CTFiles cts)
+
+type family CTFile c :: [Symbol] where
+  CTFile (HTML fp)   = '[fp]
+  CTFile (Tpl ct fp) = '[fp]
+  CTFile a           = '[]
+
+templates :: Proxy api -> Proxy (TemplateFiles api)
+templates Proxy = Proxy
+
+templateFiles :: Reify (TemplateFiles api) => Proxy api -> [FilePath]
+templateFiles = reify . templates
+
+-- | An opaque "compiled-template store".
+--
+-- The only way to get a value of this type is to use
+-- 'Servant.EDE.loadTemplates' on a proxy of your API.
+--
+-- This ensures that when we lookup a template (in order
+-- to render it) in our 'Templates' store, we are
+-- guaranteed to find it.
+newtype Templates = Templates (HashMap String Template)
+  deriving Eq
+
+templateMap :: Templates -> HashMap String Template
+templateMap (Templates m) = m
+
+instance Semigroup Templates where
+  Templates a <> Templates b = Templates (a <> b)
+
+instance Monoid Templates where
+  mempty = Templates mempty
+
+  a `mappend` b = a <> b
+
+tpl :: FilePath -> Template -> Templates
+tpl fp t = Templates $ HM.singleton fp t
+
+-- | A 'TemplateError' is a pair of a template filename
+--   and the error string for that file.
+type TemplateError = (FilePath, String)
+
+-- | A list of 'TemplateError's.
+type Errors = [TemplateError]
+
+err :: Show a => FilePath -> a -> Errors
+err fp d = [(fp, show d)]
+
+processFile :: MonadIO m => FilePath -> FilePath -> ValidateT Errors m Templates
+processFile d fp = validate . liftIO $ parseFile' (d </> fp)
+
+  where parseFile' f = fmap validateResult (parseFile f)
+        validateResult (Success t) = OK (tpl fp t)
+        validateResult (Failure e) = NotOK (err fp e)
diff --git a/src/Servant/EDE/Internal.hs b/src/Servant/EDE/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/EDE/Internal.hs
@@ -0,0 +1,10 @@
+module Servant.EDE.Internal
+  ( module Servant.EDE.Internal.Reify
+  , module Servant.EDE.Internal.ToObject
+  , module Servant.EDE.Internal.Validate
+  ) where
+
+import Servant.EDE.Internal.Reify
+import Servant.EDE.Internal.ToObject
+import Servant.EDE.Internal.Validate
+
diff --git a/src/Servant/EDE/Internal/Reify.hs b/src/Servant/EDE/Internal/Reify.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/EDE/Internal/Reify.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Servant.EDE.Internal.Reify (Reify(..)) where
+
+import Data.Proxy
+import GHC.TypeLits
+
+-- | Helper class to reify a type-level list of strings
+--   into a value-level list of string. Used to turn
+--   the type-level list of template file names into
+--   a value-level list.
+class Reify (symbols :: [Symbol]) where
+  reify :: Proxy symbols -> [String]
+
+instance Reify '[] where
+  reify _ = []
+
+instance (KnownSymbol s, Reify symbols)
+      => Reify (s ': symbols) where
+  reify _ = symbolVal ps : reify psymbols
+
+    where ps = Proxy :: Proxy s
+          psymbols = Proxy :: Proxy symbols
diff --git a/src/Servant/EDE/Internal/ToObject.hs b/src/Servant/EDE/Internal/ToObject.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/EDE/Internal/ToObject.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleInstances #-}
+-- {-# LANGUAGE OverloadedStrings #-}
+module Servant.EDE.Internal.ToObject where
+
+import Data.Aeson
+import Data.HashMap.Strict
+import Data.Monoid
+import Data.Text
+import GHC.Generics
+
+-- | Turn haskell values into JSON objects.
+--
+-- This is the mechanism used by EDE to marshall data from Haskell
+-- to the templates. The rendering is then just about feeding the
+-- resulting 'Object' to a compiled 'Template'. Example:
+--
+-- > import Text.EDE
+-- >
+-- > data User = User { name :: String, age :: Int }
+-- >
+-- > instance ToObject User where
+-- >   toObject user =
+-- >     fromPairs [ "name" .= name user
+-- >               , "age"  .= age user
+-- >               ]
+--
+-- However, you're not forced to write the instance yourself for such a type.
+-- Indeed, for any record type (i.e a datatype with a single constructor and
+-- with field selectors) you can let @GHC.Generics@ derive the 'ToObject' instance
+-- for you.
+--
+-- > data User = User { name :: String, age :: Int } deriving Generic
+-- > instance ToObject User
+--
+-- This will generate an equivalent instance to the previous one.
+class ToObject a where
+
+  -- | Turn values of type @a@ into JSON 'Object's.
+  --
+  -- @ 
+  -- -- Reminder:
+  -- type Object = 'HashMap' 'Text' 'Value'
+  -- @
+  toObject :: a -> Object
+  
+  default toObject :: (Generic a, GToObject (Rep a)) => a -> Object
+  toObject = genericToObject
+
+instance ToObject (HashMap Text Value) where
+  toObject = id
+
+class GToObject f where
+  gtoObject :: f a -> Object
+
+instance GToObject V1 where
+  gtoObject _ = mempty
+
+instance GToObject U1 where
+  gtoObject U1 = mempty
+
+instance (GToObject f, GToObject g)
+      => GToObject (f :*: g) where
+  gtoObject (f :*: g) = gtoObject f <> gtoObject g
+
+instance GToObject a => GToObject (M1 D d a) where
+  gtoObject (M1 x) = gtoObject x
+
+instance GToObject a => GToObject (M1 C c a) where
+  gtoObject (M1 x) = gtoObject x
+
+instance (Selector s, ToJSON a) => GToObject (M1 S s (K1 r a)) where
+  gtoObject s@(M1 (K1 x)) = fromList [(fieldname, value)]
+    where fieldname = pack (selName s)
+          value     = toJSON x
+
+genericToObject :: (Generic a, GToObject (Rep a)) => a -> Object
+genericToObject = gtoObject . from
diff --git a/src/Servant/EDE/Internal/Validate.hs b/src/Servant/EDE/Internal/Validate.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/EDE/Internal/Validate.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE CPP #-}
+module Servant.EDE.Internal.Validate where
+
+#if __GLASGOW_HASKELL__ < 710
+import Control.Applicative
+import Data.Foldable
+import Data.Traversable
+#endif
+
+import Data.Functor.Compose
+import Data.Semigroup
+
+data Validated e a = OK a | NotOK e
+  deriving (Eq, Show)
+
+instance Functor (Validated e) where
+  fmap f (OK x)    = OK (f x)
+  fmap _ (NotOK e) = NotOK e
+
+instance Semigroup e => Applicative (Validated e) where
+  pure x = OK x
+
+  OK f    <*> OK x     = OK (f x)
+  OK _    <*> NotOK e  = NotOK e
+  NotOK e <*> OK _     = NotOK e
+  NotOK e <*> NotOK e' = NotOK (e <> e')
+
+instance Foldable (Validated e) where
+  foldMap f (OK x)    = f x
+  foldMap _ (NotOK _) = mempty
+
+instance Traversable (Validated e) where
+  traverse f (OK x)    = fmap OK (f x)
+  traverse _ (NotOK x) = pure (NotOK x)
+
+instance (Semigroup e, Semigroup a) => Semigroup (Validated e a) where
+  NotOK e <> NotOK e' = NotOK (e <> e')
+  NotOK e <> OK _     = NotOK e
+  OK a    <> OK b     = OK (a <> b)
+  OK _    <> NotOK e  = NotOK e
+
+validateEither :: Either e a -> Validated e a
+validateEither (Left e)  = NotOK e
+validateEither (Right x) = OK x
+
+eitherValidate :: Validated e a -> Either e a
+eitherValidate (OK x)    = Right x
+eitherValidate (NotOK e) = Left e
+
+ok :: Applicative m => a -> ValidateT e m a
+ok = VT . pure . OK
+
+no :: Applicative m => e -> ValidateT e m a
+no = VT . pure . NotOK
+
+validated :: (e -> r) -> (a -> r) -> Validated e a -> r
+validated f _ (NotOK e) = f e
+validated _ f (OK x)    = f x
+
+newtype ValidateT e m a = VT
+  { runValidateT :: m (Validated e a) }
+
+validate :: m (Validated e a) -> ValidateT e m a
+validate = VT
+
+instance Functor m => Functor (ValidateT e m) where
+  fmap f (VT m) = VT $ fmap (fmap f) m
+
+instance (Applicative m, Semigroup e) => Applicative (ValidateT e m) where
+  pure = VT . pure . pure
+
+  VT f <*> VT x = VT . getCompose $ Compose f <*> Compose x
+
+instance (Applicative m, Semigroup e, Semigroup a) => Semigroup (ValidateT e m a) where
+  VT a <> VT b = VT $ (<>) <$> a <*> b
diff --git a/src/Servant/HTML/EDE.hs b/src/Servant/HTML/EDE.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE.hs
+++ /dev/null
@@ -1,229 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
--- |
--- Module:      Servant.HTML.EDE
--- Copyright:   (c) 2015 Alp Mestanogullari
--- License:     BSD3
--- Maintainer:  Alp Mestanogullari <alpmestan@gmail.com>
--- Stability:   experimental
---
--- Combinators for rendering <http://hackage.haskell.org/package/ede ede>
--- templates in servant web applications.
-module Servant.HTML.EDE (
-    -- * Introduction
-    -- $intro
-
-    -- * Explicitly binding data to a template
-    -- $explicit
-
-    -- * Template rendering as a content-type
-    -- $contenttype
-    
-    -- * Reference
-
-    -- ** 'Tpl' combinator, for explicit data binding
-    Tpl
-  
-  , -- ** 'HTML' content type, for serializing data types to HTML
-    HTML
-  , ToObject(..)
-
-  , -- ** Loading templates
-    loadTemplates
-  , TemplateError
-  , Errors
-
-  , -- ** Helpers
-    TemplateFiles
-  , Reify(..)
-
-  , -- * Global template store
-    -- $templatestore
-  ) where
-
-import Control.Applicative
-import Control.Concurrent.MVar
-import Control.Monad.IO.Class
-import Data.Aeson
-import Data.Foldable
-import Data.HashMap.Strict
-import Data.Traversable
-import Servant
-import Servant.HTML.EDE.Internal
-
--- | Same as 'loadTemplates', except that it initializes a global
---   template store (i.e a 'Templates' value) and fills it with
---   the resulting compiled templates if all of them are compiled
---   successfully. If that's not the case, the global template store
---   (under an 'MVar') is left empty.
---
---   /IMPORTANT/: Must /always/ be called before starting your /servant/ application.
-loadTemplates :: (Reify (TemplateFiles api), Applicative m, MonadIO m)
-              => Proxy api
-              -> FilePath -- ^ root directory for the templates
-              -> m Errors
-loadTemplates proxy dir = do
-  res <- loadTemplates' proxy dir
-  case res of
-    Left errs  -> return errs
-    Right tpls -> do
-      liftIO $ putMVar __template_store tpls
-      return []
-
-loadTemplates' :: (Reify (TemplateFiles api), Applicative m, MonadIO m)
-               => Proxy api
-               -> FilePath   -- ^ root directory for the templates
-               -> m (Either Errors Templates)
-loadTemplates' proxy templatedir =
-  fmap (eitherValidate . fmap fold) . runValidateT $
-    traverse (processFile templatedir) files
-
-  where files :: [FilePath]
-        files = templateFiles proxy
-
--- $intro
---
--- The <http://hackage.haskell.org/package/ede ede> library provides
--- a reasonably good template engine. This package explores
--- a smooth integration of /ede/ into <http://haskell-servant.github.io/ servant>
--- through two combinators.
-
--- $explicit
---
--- The first combinator is 'Tpl', which is used for generating web pages
--- from /ede/ templates by explicitly returning an 'Object'
--- (which is a synonym for @'HashMap' 'Text' 'Value'@, i.e a /JSON object/)
--- from the handler which will then be rendered against a given template.
---
--- @
--- -- we want our template file, index.html,
--- -- to be rendered under /index
--- type API = "index" :> 'Tpl' "index.html"
---
--- api :: 'Proxy' API
--- api = Proxy
---
--- server :: 'Server' API
--- server = return indexData
---
---   where indexData :: 'Object'
---         indexData =
---           HM.fromList [ ("company_name", "Foo Inc.")
---                       , ("ceo", "Bar Baz")
---                       ]
---
--- main :: IO ()
--- main = do
---   -- this tells the library to look for index.html
---   -- under the ./templates directory
---   'loadTemplates' api "./templates"
---   run 8080 server
--- @
---
--- Note that if your template doesn't need any data, you can just
--- return the empty 'Object', with "Data.Monoid"\'s 'mempty'.
---
--- The call to 'loadTemplates' is mandatory. It loads and compiles all the
--- templates used in your API and puts them in a global \"compiled template store\".
--- I'm not really satisfied with this, see the /Global template store/ section
--- for more on this topic.
-
--- $contenttype
---
--- The other way to use this package is reminiscent of how you can render HTML
--- with <http://hackage.haskell.org/package/servant-blaze servant-blaze> or
--- its cousin <http://hackage.haskell.org/package/servant-lucid servant-lucid>.
--- Indeed, this package provides an 'HTML' content type just like the two
--- aforementionned libraries. However, unlike in these packages, this 'HTML'
--- type is parametrised by a type-level string meant to be the name of the
--- template file (or path to the template file starting from a \"root\" directory
--- of templates).
---
--- In the same way that /servant/'s standard 'JSON' combinator
--- carries the precise way in which we encode haskell values to JSON,
--- in addition to representing the @application/json@ content type,
--- 'HTML' carries the template used to render values of a given type.
---
--- If we wanted to have a @/user@ endpoint accessible in JSON or HTML,
--- returning a user, we could write:
---
--- @
--- type UserAPI = "user" :> 'Get' '['JSON', 'HTML' "user.tpl"] User
---
--- userAPI :: Proxy UserAPI
--- userAPI = Proxy
--- @
---
--- How, then, can /servant/ know how to marshall @User@ to the template
--- in order to render it? Simple, you just have to provide an instance of
--- the following 'ToObject' class:
---
--- @
--- class ToObject a where
---   toObject :: a -> 'Object'
--- @
---
--- If our @User@ data type is:
---
--- > data User = User { name :: String, age :: Int }
---
--- we can simply do, using functions from "Text.EDE":
---
--- @
--- instance ToObject User where
---   toObject u =
---     fromPairs [ "name" .= name u
---               , "age"  .= age u
---               ]
--- @
---
--- However, this is actually not necessary. This library provides can
--- derive the 'ToObject' instance for you as long as your data type
--- derives the "GHC.Generics.Generic" class, which can be done by specifying
--- @{-# LANGUAGE DeriveGeneric #-}@ at the top of your module, adding
--- @import GHC.Generics@ and by changing the @User@ data type declaration to:
---
--- > data User = User { name :: String, age :: Int } deriving Generic
---
--- You can then simply write:
---
--- > instance ToObject User
---
--- and the library will figure out how to encode @User@ to JSON for you.
--- /IMPORTANT/: This only works with data types with a single record and
--- field selectors.
---
--- Now we can put this all to work with a simple webservice:
---
--- @
--- server :: Server UserAPI
--- server = return (User "lambdabot" 31)
---
--- main :: IO ()
--- main = do
---   loadTemplates userAPI "./templates"
---   run 8082 (serve userAPI server)
--- @
---
--- Again, the call to 'loadTemplates' is mandatory because the 'HTML'
--- content type relies on having its hands on already-compiled templates.
---
--- You can now write a @user.tpl@ template under the @./templates@ directory
--- using any of <http://hackage.haskell.org/package/ede ede>'s constructs,
--- assuming that a @name@ string variable and an @age@ int variable are in scope.
-
--- $templatestore
---
--- Why have a global template store? Well, while for 'Tpl' we can run arbitrary code
--- in the handlers, take arguments and what not, that's not the case when writing the
--- 'MimeRender' instance for 'HTML'.
---
--- All we have is a value of some type and we have to pull a compiled template out of
--- thin air. That's why we use a global 'MVar'-protected template store indexed by filename.
--- It's filled once at the beginning when you call 'loadTemplates' and is then only accessed
--- in a /read-only/ fashion. I would be interested in hearing about any suggestion,
--- improvement or replacement for this. If you have an idea, feel free to shoot me an
--- email at the address specified in the cabal description.
diff --git a/src/Servant/HTML/EDE/Internal.hs b/src/Servant/HTML/EDE/Internal.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE/Internal.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-module Servant.HTML.EDE.Internal
-  ( module Servant.HTML.EDE.Internal.Reify
-  , module Servant.HTML.EDE.Internal.Templates
-  , module Servant.HTML.EDE.Internal.ToObject
-  , module Servant.HTML.EDE.Internal.Validate
-  ) where
-
-import Servant.HTML.EDE.Internal.Reify
-import Servant.HTML.EDE.Internal.Templates
-import Servant.HTML.EDE.Internal.ToObject
-import Servant.HTML.EDE.Internal.Validate
-
diff --git a/src/Servant/HTML/EDE/Internal/Reify.hs b/src/Servant/HTML/EDE/Internal/Reify.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE/Internal/Reify.hs
+++ /dev/null
@@ -1,25 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-module Servant.HTML.EDE.Internal.Reify (Reify(..)) where
-
-import Data.Proxy
-import GHC.TypeLits
-
--- | Helper class to reify a type-level list of strings
---   into a value-level list of string. Used to turn
---   the type-level list of template file names into
---   a value-level list.
-class Reify (symbols :: [Symbol]) where
-  reify :: Proxy symbols -> [String]
-
-instance Reify '[] where
-  reify _ = []
-
-instance (KnownSymbol s, Reify symbols)
-      => Reify (s ': symbols) where
-  reify _ = symbolVal ps : reify psymbols
-
-    where ps = Proxy :: Proxy s
-          psymbols = Proxy :: Proxy symbols
diff --git a/src/Servant/HTML/EDE/Internal/Templates.hs b/src/Servant/HTML/EDE/Internal/Templates.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE/Internal/Templates.hs
+++ /dev/null
@@ -1,224 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-module Servant.HTML.EDE.Internal.Templates
-  ( Tpl
-  , HTML
-  , Templates(..)
-  , templateMap
-  , __template_store
-  , TemplateFiles
-  , TemplateError
-  , Errors
-  , processFile
-  , templateFiles
-  ) where
-
-import Control.Concurrent.MVar
-import Control.Monad.IO.Class
-import Control.Monad.Trans.Either
-import Data.Aeson (Object)
-import Data.ByteString.Lazy.Char8 (pack)
-import Data.HashMap.Strict
-import Data.Proxy
-import Data.Semigroup
-import Data.Text.Lazy.Encoding (encodeUtf8)
-import GHC.TypeLits
-import Network.HTTP.Media hiding (Accept)
-import Network.HTTP.Types
-import Network.Wai
-import Servant
-import Servant.HTML.EDE.Internal.Reify
-import Servant.HTML.EDE.Internal.ToObject
-import Servant.HTML.EDE.Internal.Validate
-import Servant.Server.Internal
-import Servant.Server.Internal.ServantErr
-import System.FilePath
-import System.IO.Unsafe (unsafePerformIO)
-import Text.EDE
-
-import qualified Data.HashMap.Strict as HM
-
-__template_store :: MVar Templates
-__template_store = unsafePerformIO newEmptyMVar
-
--- | Combinator for serving EDE templates without arguments. Usage:
---
--- > type API = "index" :> Tpl "index.tpl"
--- >       :<|> "about" :> Tpl "about.tpl"
--- >
--- > api :: Proxy API
--- > api = Proxy
--- >
--- > server :: Templates -> Server API
--- > server tpls = return mempty :<|> return mempty
--- >
--- > main :: IO ()
--- > main = do
--- >   loadTemplates_ api "./templates"
--- >   run 8080 (serve api server)
-data Tpl (tplfile :: Symbol)
-
-
--- | The so-called "request handler" for an endpoint ending
---   with 'Tpl' just has to be the opaque 'Templates' value
---   returned by 'Servant.HTML.EDE.loadTemplates' applied to your API, which
---   is just a compiled template store indexed by file name.
-instance KnownSymbol tplfile => HasServer (Tpl tplfile) where
-  type ServerT (Tpl tplfile) m = m Object
-
-  route Proxy mobj request respond
-    | pathIsEmpty request && requestMethod request == methodGet = do
-        tpls <- getTemplates
-        val <- runEitherT mobj
-        case val of
-          Left e -> respond . succeedWith $ responseServantErr e
-          Right v  -> 
-            case mbody tpls v of
-              Success body -> respond . succeedWith $
-                responseLBS ok200 [("Content-Type", "text/html")] (encodeUtf8 body)
-              Failure doc  -> respond . succeedWith $
-                responseLBS status500 [] ("template error: " <> pack (show doc))
-
-    | pathIsEmpty request && requestMethod request /= methodGet =
-        respond (failWith WrongMethod)
-
-    | otherwise = respond (failWith NotFound)
-
-    where filename = symbolVal (Proxy :: Proxy tplfile)
-          mbody ts val = render (ts HM.! filename) val
-          getTemplates = fmap templateMap (readMVar __template_store)
-
--- | 'HTML' content type, but more than just that.
---
---   'HTML' takes a type-level string which is
---   a filename for the template you want to use to
---   render values. Example:
---
--- @
--- type UserAPI = "user" :> Get '[JSON, HTML "user.tpl"] User
---
--- userAPI :: Proxy UserAPI
--- userAPI = Proxy
---
--- data User = User { name :: String, age :: Int } deriving Generic
---
--- instance ToJSON User
--- instance ToObject User
---
--- server :: Server API
--- server = return (User "lambdabot" 31)
---
--- main :: IO ()
--- main = do
---   loadTemplates userAPI "./templates"
---   run 8082 (serve userAPI server)
--- @
---
--- This will look for a template at @.\/templates\/user.tpl@, which could
--- for example be:
---
--- > <ul>
--- >   <li><strong>Name:</strong> {{ name }}</li>
--- >   <li><strong>Age:</strong> {{ age }}</li>
--- > </ul>
-data HTML (tplfile :: Symbol)
-
--- | @text\/html;charset=utf-8@
-instance Accept (HTML tplfile) where
-  contentType _ = "text" // "html" /: ("charset", "utf-8")
-
-instance (KnownSymbol tplfile, ToObject a)
-      => MimeRender (HTML tplfile) a where
-  mimeRender _ val = encodeUtf8 . result (error . show) id $
-    render templ (toObject val)
-
-    where templ = tmap ! filename
-          filename = symbolVal (Proxy :: Proxy tplfile)
-          tmap = templateMap $ unsafePerformIO (readMVar __template_store)
-
-type family Append (xs :: [k]) (ys :: [k]) :: [k] where
-  Append '[]       ys = ys
-  Append (x ': xs) ys = x ': Append xs ys
-
-type family Member (x :: k) (xs :: [k]) :: Bool where
-  Member x (x ': xs) = 'True
-  Member x (y ': xs) = Member x xs
-  Member x       '[] = False
-
--- | Collect all the template filenames of an API as a type-level
---   list of strings, by simply looking at all occurences of the
---   'Tpl' and 'HTML' combinators and keeping the filenames associated to them.
-type family TemplateFiles (api :: k) :: [Symbol]
-type instance TemplateFiles (a :<|> b)    = Append (TemplateFiles a) (TemplateFiles b)
-type instance TemplateFiles (a :> r)      = TemplateFiles r
-type instance TemplateFiles (Tpl f)       = '[f]
-type instance TemplateFiles (Delete cs a) = CTFiles cs
-type instance TemplateFiles (Get cs a)    = CTFiles cs
-type instance TemplateFiles (Patch cs a)  = CTFiles cs
-type instance TemplateFiles (Post cs a)   = CTFiles cs
-type instance TemplateFiles (Put cs a)    = CTFiles cs
-type instance TemplateFiles Raw           = '[]
-
-type family CTFiles (cts :: [*]) :: [Symbol] where
-  CTFiles '[]        = '[]
-  CTFiles (c ': cts) = Append (CTFile c) (CTFiles cts)
-
-type family CTFile c :: [Symbol] where
-  CTFile (HTML fp) = '[fp]
-  CTFile         a = '[]
-
-templates :: Proxy api -> Proxy (TemplateFiles api)
-templates Proxy = Proxy
-
-templateFiles :: Reify (TemplateFiles api) => Proxy api -> [FilePath]
-templateFiles = reify . templates
-
--- | An opaque "compiled-template store".
---
--- The only way to get a value of this type is to use
--- 'Servant.EDE.loadTemplates' on a proxy of your API.
---
--- This ensures that when we lookup a template (in order
--- to render it) in our 'Templates' store, we are
--- guaranteed to find it.
-newtype Templates = Templates (HashMap String Template)
-  deriving Eq
-
-templateMap :: Templates -> HashMap String Template
-templateMap (Templates m) = m
-
-instance Semigroup Templates where
-  Templates a <> Templates b = Templates (a <> b)
-
-instance Monoid Templates where
-  mempty = Templates mempty
-
-  a `mappend` b = a <> b
-
-tpl :: FilePath -> Template -> Templates
-tpl fp t = Templates $ HM.singleton fp t
-
--- | A 'TemplateError' is a pair of a template filename
---   and the error string for that file.
-type TemplateError = (FilePath, String)
-
--- | A list of 'TemplateError's.
-type Errors = [TemplateError]
-
-err :: Show a => FilePath -> a -> Errors
-err fp d = [(fp, show d)]
-
-processFile :: MonadIO m => FilePath -> FilePath -> ValidateT Errors m Templates
-processFile d fp = validate . liftIO $ parseFile' (d </> fp)
-
-  where parseFile' f = fmap validateResult (parseFile f)
-        validateResult (Success t) = OK (tpl fp t)
-        validateResult (Failure e) = NotOK (err fp e)
diff --git a/src/Servant/HTML/EDE/Internal/ToObject.hs b/src/Servant/HTML/EDE/Internal/ToObject.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE/Internal/ToObject.hs
+++ /dev/null
@@ -1,97 +0,0 @@
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE DefaultSignatures #-}
-{-# LANGUAGE FlexibleInstances #-}
--- {-# LANGUAGE OverloadedStrings #-}
-module Servant.HTML.EDE.Internal.ToObject where
-
-import Data.Aeson
-import Data.HashMap.Strict
-import Data.Monoid
-import Data.Text
-import GHC.Generics
-
--- | Turn haskell values into JSON objects.
---
--- This is the mechanism used by EDE to marshall data from Haskell
--- to the templates. The rendering is then just about feeding the
--- resulting 'Object' to a compiled 'Template'. Example:
---
--- > import Text.EDE
--- >
--- > data User = User { name :: String, age :: Int }
--- > instance ToObject User where
--- >   toObject user =
--- >     fromPairs [ "name" .= name user
--- >               , "age"  .= age user
--- >               ]
---
--- However, you're not forced to write the instance yourself for such a type.
--- Indeed, for any record type (i.e a datatype with a single constructor and
--- with field selectors) you can let @GHC.Generics@ derive the 'ToObject' instance
--- for you.
---
--- > data User = User { name :: String, age :: Int } deriving Generic
--- > instance ToObject User
---
--- This will generate an equivalent instance to the previous one.
-class ToObject a where
-
-  -- | Turn values of type @a@ into JSON 'Object's.
-  --
-  -- @ 
-  -- -- Reminder:
-  -- type Object = 'HashMap' 'Text' 'Value'
-  -- @
-  toObject :: a -> Object
-  
-  default toObject :: (Generic a, GToObject (Rep a)) => a -> Object
-  toObject = genericToObject
-
-instance ToObject (HashMap Text Value) where
-  toObject = id
-
-class GToObject f where
-  gtoObject :: f a -> Object
-
-instance GToObject V1 where
-  gtoObject _ = mempty
-
-instance GToObject U1 where
-  gtoObject U1 = mempty
-
-instance (GToObject f, GToObject g)
-      => GToObject (f :*: g) where
-  gtoObject (f :*: g) = gtoObject f <> gtoObject g
-
-instance GToObject a => GToObject (M1 D d a) where
-  gtoObject (M1 x) = gtoObject x
-
-instance GToObject a => GToObject (M1 C c a) where
-  gtoObject (M1 x) = gtoObject x
-
-instance (Selector s, ToJSON a) => GToObject (M1 S s (K1 r a)) where
-  gtoObject s@(M1 (K1 x)) = fromList [(fieldname, value)]
-    where fieldname = pack (selName s)
-          value     = toJSON x
-
-genericToObject :: (Generic a, GToObject (Rep a)) => a -> Object
-genericToObject = gtoObject . from
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Servant/HTML/EDE/Internal/Validate.hs b/src/Servant/HTML/EDE/Internal/Validate.hs
deleted file mode 100644
--- a/src/Servant/HTML/EDE/Internal/Validate.hs
+++ /dev/null
@@ -1,71 +0,0 @@
-module Servant.HTML.EDE.Internal.Validate where
-
-import Control.Applicative
-import Data.Foldable
-import Data.Traversable
-import Data.Functor.Compose
-import Data.Semigroup
-
-data Validated e a = OK a | NotOK e
-  deriving (Eq, Show)
-
-instance Functor (Validated e) where
-  fmap f (OK x)    = OK (f x)
-  fmap _ (NotOK e) = NotOK e
-
-instance Semigroup e => Applicative (Validated e) where
-  pure x = OK x
-
-  OK f    <*> OK x     = OK (f x)
-  OK _    <*> NotOK e  = NotOK e
-  NotOK e <*> OK _     = NotOK e
-  NotOK e <*> NotOK e' = NotOK (e <> e')
-
-instance Foldable (Validated e) where
-  foldMap f (OK x)    = f x
-  foldMap _ (NotOK _) = mempty
-
-instance Traversable (Validated e) where
-  traverse f (OK x)    = fmap OK (f x)
-  traverse _ (NotOK x) = pure (NotOK x)
-
-instance (Semigroup e, Semigroup a) => Semigroup (Validated e a) where
-  NotOK e <> NotOK e' = NotOK (e <> e')
-  NotOK e <> OK _     = NotOK e
-  OK a    <> OK b     = OK (a <> b)
-  OK _    <> NotOK e  = NotOK e
-
-validateEither :: Either e a -> Validated e a
-validateEither (Left e)  = NotOK e
-validateEither (Right x) = OK x
-
-eitherValidate :: Validated e a -> Either e a
-eitherValidate (OK x)    = Right x
-eitherValidate (NotOK e) = Left e
-
-ok :: Applicative m => a -> ValidateT e m a
-ok = VT . pure . OK
-
-no :: Applicative m => e -> ValidateT e m a
-no = VT . pure . NotOK
-
-validated :: (e -> r) -> (a -> r) -> Validated e a -> r
-validated f _ (NotOK e) = f e
-validated _ f (OK x)    = f x
-
-newtype ValidateT e m a = VT
-  { runValidateT :: m (Validated e a) }
-
-validate :: m (Validated e a) -> ValidateT e m a
-validate = VT
-
-instance Functor m => Functor (ValidateT e m) where
-  fmap f (VT m) = VT $ fmap (fmap f) m
-
-instance (Applicative m, Semigroup e) => Applicative (ValidateT e m) where
-  pure = VT . pure . pure
-
-  VT f <*> VT x = VT . getCompose $ Compose f <*> Compose x
-
-instance (Applicative m, Semigroup e, Semigroup a) => Semigroup (ValidateT e m a) where
-  VT a <> VT b = VT $ (<>) <$> a <*> b
