@@ -111,11 +111,11 @@ corresponding API type.
111The first thing to know about the `Server` type family is that behind the
111The first thing to know about the `Server` type family is that behind the
112scenes it will drive the routing, letting you focus only on the business
112scenes it will drive the routing, letting you focus only on the business
113logic. The second thing to know is that for each endpoint, your handlers will
113logic. The second thing to know is that for each endpoint, your handlers will
114−by default run in the `ExceptT ServantErr IO` monad. This is overridable very
114+by default run in the `Handler` monad. This is overridable very
115easily, as explained near the end of this guide. Third thing, the type of the
115easily, as explained near the end of this guide. Third thing, the type of the
116value returned in that monad must be the same as the second argument of the
116value returned in that monad must be the same as the second argument of the
117HTTP method combinator used for the corresponding endpoint. In our case, it
117HTTP method combinator used for the corresponding endpoint. In our case, it
118−means we must provide a handler of type `ExceptT ServantErr IO [User]`. Well,
118+means we must provide a handler of type `Handler [User]`. Well,
119we have a monad, let's just `return` our list:
119we have a monad, let's just `return` our list:
121``` haskell
121``` haskell
@@ -269,15 +269,15 @@ server3 = position
269 :<|> hello
269 :<|> hello
270 :<|> marketing
270 :<|> marketing
272− where position :: Int -> Int -> ExceptT ServantErr IO Position
272+ where position :: Int -> Int -> Handler Position
273 position x y = return (Position x y)
273 position x y = return (Position x y)
275− hello :: Maybe String -> ExceptT ServantErr IO HelloMessage
275+ hello :: Maybe String -> Handler HelloMessage
276 hello mname = return . HelloMessage $ case mname of
276 hello mname = return . HelloMessage $ case mname of
277 Nothing -> "Hello, anonymous coward"
277 Nothing -> "Hello, anonymous coward"
278 Just n -> "Hello, " ++ n
278 Just n -> "Hello, " ++ n
280− marketing :: ClientInfo -> ExceptT ServantErr IO Email
280+ marketing :: ClientInfo -> Handler Email
281 marketing clientinfo = return (emailForClient clientinfo)
281 marketing clientinfo = return (emailForClient clientinfo)
@@ -307,7 +307,7 @@ $ curl -X POST -d '{"clientName":"Alp Mestanogullari", "clientEmail" : "alp@foo.
308For reference, here's a list of some combinators from **servant**:
308For reference, here's a list of some combinators from **servant**:
310− > - `Delete`, `Get`, `Patch`, `Post`, `Put`: these do not become arguments. They provide the return type of handlers, which usually is `ExceptT ServantErr IO <something>`.
310+ > - `Delete`, `Get`, `Patch`, `Post`, `Put`: these do not become arguments. They provide the return type of handlers, which usually is `Handler <something>`.
311 > - `Capture "something" a` becomes an argument of type `a`.
311 > - `Capture "something" a` becomes an argument of type `a`.
312 > - `QueryParam "something" a`, `Header "something" a` all become arguments of type `Maybe a`, because there might be no value at all specified by the client for these.
312 > - `QueryParam "something" a`, `Header "something" a` all become arguments of type `Maybe a`, because there might be no value at all specified by the client for these.
313 > - `QueryFlag "something"` gets turned into an argument of type `Bool`.
313 > - `QueryFlag "something"` gets turned into an argument of type `Bool`.
@@ -601,11 +601,10 @@ $ curl -H 'Accept: text/html' http://localhost:8081/persons
601# or just point your browser to http://localhost:8081/persons
601# or just point your browser to http://localhost:8081/persons
604−## The `ExceptT ServantErr IO` monad
604+## The `Handler` monad
606−At the heart of the handlers is the monad they run in, namely `ExceptT
606+At the heart of the handlers is the monad they run in, namely `ExceptT ServantErr IO`
608−([haddock documentation for `ExceptT`](http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)).
607+([haddock documentation for `ExceptT`](http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)), which is aliased as `Handler`.
609One might wonder: why this monad? The answer is that it is the
608One might wonder: why this monad? The answer is that it is the
610simplest monad with the following properties:
609simplest monad with the following properties:
@@ -621,7 +620,7 @@ Let's recall some definitions.
621newtype ExceptT e m a = ExceptT (m (Either e a))
620newtype ExceptT e m a = ExceptT (m (Either e a))
624−In short, this means that a handler of type `ExceptT ServantErr IO a` is simply
623+In short, this means that a handler of type `Handler a` is simply
625equivalent to a computation of type `IO (Either ServantErr a)`, that is, an IO
624equivalent to a computation of type `IO (Either ServantErr a)`, that is, an IO
626action that either returns an error or a result.
625action that either returns an error or a result.
@@ -688,7 +687,7 @@ module. If you want to use these values but add a body or some headers, just
688use record update syntax:
687use record update syntax:
690``` haskell
689``` haskell
691−failingHandler :: ExceptT ServantErr IO ()
690+failingHandler :: Handler ()
692failingHandler = throwError myerr
691failingHandler = throwError myerr
694 where myerr :: ServantErr
693 where myerr :: ServantErr
@@ -826,11 +825,11 @@ However, you have to be aware that this has an effect on the type of the
826corresponding `Server`:
825corresponding `Server`:
828``` haskell ignore
827``` haskell ignore
829−Server UserAPI3 = (Int -> ExceptT ServantErr IO User)
828+Server UserAPI3 = (Int -> Handler User)
830− :<|> (Int -> ExceptT ServantErr IO ())
829+ :<|> (Int -> Handler ())
832−Server UserAPI4 = Int -> ( ExceptT ServantErr IO User
831+Server UserAPI4 = Int -> ( Handler User
833− :<|> ExceptT ServantErr IO ()
832+ :<|> Handler ()
@@ -842,10 +841,10 @@ computations in `ExceptT`, with no arguments. In other words:
842server8 :: Server UserAPI3
841server8 :: Server UserAPI3
843server8 = getUser :<|> deleteUser
842server8 = getUser :<|> deleteUser
845− where getUser :: Int -> ExceptT ServantErr IO User
844+ where getUser :: Int -> Handler User
846 getUser _userid = error "..."
845 getUser _userid = error "..."
848− deleteUser :: Int -> ExceptT ServantErr IO ()
847+ deleteUser :: Int -> Handler ()
849 deleteUser _userid = error "..."
848 deleteUser _userid = error "..."
851-- notice how getUser and deleteUser
850-- notice how getUser and deleteUser
@@ -854,10 +853,10 @@ server8 = getUser :<|> deleteUser
854server9 :: Server UserAPI4
853server9 :: Server UserAPI4
855server9 userid = getUser userid :<|> deleteUser userid
854server9 userid = getUser userid :<|> deleteUser userid
857− where getUser :: Int -> ExceptT ServantErr IO User
856+ where getUser :: Int -> Handler User
858 getUser = error "..."
857 getUser = error "..."
860− deleteUser :: Int -> ExceptT ServantErr IO ()
859+ deleteUser :: Int -> Handler ()
861 deleteUser = error "..."
860 deleteUser = error "..."
@@ -905,23 +904,23 @@ type UsersAPI =
905usersServer :: Server UsersAPI
904usersServer :: Server UsersAPI
906usersServer = getUsers :<|> newUser :<|> userOperations
905usersServer = getUsers :<|> newUser :<|> userOperations
908− where getUsers :: ExceptT ServantErr IO [User]
907+ where getUsers :: Handler [User]
909 getUsers = error "..."
908 getUsers = error "..."
911− newUser :: User -> ExceptT ServantErr IO ()
910+ newUser :: User -> Handler ()
912 newUser = error "..."
911 newUser = error "..."
914 userOperations userid =
913 userOperations userid =
915 viewUser userid :<|> updateUser userid :<|> deleteUser userid
914 viewUser userid :<|> updateUser userid :<|> deleteUser userid
918− viewUser :: Int -> ExceptT ServantErr IO User
917+ viewUser :: Int -> Handler User
919 viewUser = error "..."
918 viewUser = error "..."
921− updateUser :: Int -> User -> ExceptT ServantErr IO ()
920+ updateUser :: Int -> User -> Handler ()
922 updateUser = error "..."
921 updateUser = error "..."
924− deleteUser :: Int -> ExceptT ServantErr IO ()
923+ deleteUser :: Int -> Handler ()
925 deleteUser = error "..."
924 deleteUser = error "..."
@@ -940,23 +939,23 @@ data Product = Product { productId :: Int }
940productsServer :: Server ProductsAPI
939productsServer :: Server ProductsAPI
941productsServer = getProducts :<|> newProduct :<|> productOperations
940productsServer = getProducts :<|> newProduct :<|> productOperations
943− where getProducts :: ExceptT ServantErr IO [Product]
942+ where getProducts :: Handler [Product]
944 getProducts = error "..."
943 getProducts = error "..."
946− newProduct :: Product -> ExceptT ServantErr IO ()
945+ newProduct :: Product -> Handler ()
947 newProduct = error "..."
946 newProduct = error "..."
949 productOperations productid =
948 productOperations productid =
950 viewProduct productid :<|> updateProduct productid :<|> deleteProduct productid
949 viewProduct productid :<|> updateProduct productid :<|> deleteProduct productid
953− viewProduct :: Int -> ExceptT ServantErr IO Product
952+ viewProduct :: Int -> Handler Product
954 viewProduct = error "..."
953 viewProduct = error "..."
956− updateProduct :: Int -> Product -> ExceptT ServantErr IO ()
955+ updateProduct :: Int -> Product -> Handler ()
957 updateProduct = error "..."
956 updateProduct = error "..."
959− deleteProduct :: Int -> ExceptT ServantErr IO ()
958+ deleteProduct :: Int -> Handler ()
960 deleteProduct = error "..."
959 deleteProduct = error "..."
@@ -985,11 +984,11 @@ type APIFor a i =
986-- Build the appropriate 'Server'
985-- Build the appropriate 'Server'
987-- given the handlers of the right type.
986-- given the handlers of the right type.
988−serverFor :: ExceptT ServantErr IO [a] -- handler for listing of 'a's
987+serverFor :: Handler [a] -- handler for listing of 'a's
989− -> (a -> ExceptT ServantErr IO ()) -- handler for adding an 'a'
988+ -> (a -> Handler ()) -- handler for adding an 'a'
990− -> (i -> ExceptT ServantErr IO a) -- handler for viewing an 'a' given its identifier of type 'i'
989+ -> (i -> Handler a) -- handler for viewing an 'a' given its identifier of type 'i'
991− -> (i -> a -> ExceptT ServantErr IO ()) -- updating an 'a' with given id
990+ -> (i -> a -> Handler ()) -- updating an 'a' with given id
992− -> (i -> ExceptT ServantErr IO ()) -- deleting an 'a' given its id
991+ -> (i -> Handler ()) -- deleting an 'a' given its id
993 -> Server (APIFor a i)
992 -> Server (APIFor a i)
994serverFor = error "..."
993serverFor = error "..."
995-- implementation left as an exercise. contact us on IRC
994-- implementation left as an exercise. contact us on IRC
@@ -998,12 +997,11 @@ serverFor = error "..."
999## Using another monad for your handlers
998## Using another monad for your handlers
1001−Remember how `Server` turns combinators for HTTP methods into `ExceptT
1000+Remember how `Server` turns combinators for HTTP methods into `Handler`? Well, actually, there's more to that. `Server` is actually a
1002−ServantErr IO`? Well, actually, there's more to that. `Server` is actually a
1003simple type synonym.
1001simple type synonym.
1005``` haskell ignore
1003``` haskell ignore
1006−type Server api = ServerT api (ExceptT ServantErr IO)
1004+type Server api = ServerT api Handler
1009`ServerT` is the actual type family that computes the required types for the
1007`ServerT` is the actual type family that computes the required types for the
@@ -1036,12 +1034,11 @@ listToMaybeNat = Nat listToMaybe -- from Data.Maybe
1037(`Nat` comes from "natural transformation", in case you're wondering.)
1035(`Nat` comes from "natural transformation", in case you're wondering.)
1039−So if you want to write handlers using another monad/type than `ExceptT
1037+So if you want to write handlers using another monad/type than `Handler`, say the `Reader String` monad, the first thing you have to
1040−ServantErr IO`, say the `Reader String` monad, the first thing you have to
1041prepare is a function:
1038prepare is a function:
1043``` haskell ignore
1040``` haskell ignore
1044−readerToHandler :: Reader String :~> ExceptT ServantErr IO
1041+readerToHandler :: Reader String :~> Handler
1047Let's start with `readerToHandler'`. We obviously have to run the `Reader`
1044Let's start with `readerToHandler'`. We obviously have to run the `Reader`
@@ -1050,10 +1047,10 @@ from that and can then just `return` it into `ExceptT`. We can then just wrap
1050that function with the `Nat` constructor to make it have the fancier type.
1047that function with the `Nat` constructor to make it have the fancier type.
1052``` haskell
1049``` haskell
1053−readerToHandler' :: forall a. Reader String a -> ExceptT ServantErr IO a
1050+readerToHandler' :: forall a. Reader String a -> Handler a
1054readerToHandler' r = return (runReader r "hi")
1051readerToHandler' r = return (runReader r "hi")
1056−readerToHandler :: Reader String :~> ExceptT ServantErr IO
1053+readerToHandler :: Reader String :~> Handler
1057readerToHandler = Nat readerToHandler'
1054readerToHandler = Nat readerToHandler'
@@ -1077,8 +1074,7 @@ readerServerT = a :<|> b
1079We unfortunately can't use `readerServerT` as an argument of `serve`, because
1076We unfortunately can't use `readerServerT` as an argument of `serve`, because
1080−`serve` wants a `Server ReaderAPI`, i.e., with handlers running in `ExceptT
1077+`serve` wants a `Server ReaderAPI`, i.e., with handlers running in `Handler`. But there's a simple solution to this.
1081−ServantErr IO`. But there's a simple solution to this.
1083### Enter `enter`
1079### Enter `enter`