Explicit ignore
This commit is contained in:
parent
5542ce8916
commit
7af73d63ea
5 changed files with 30 additions and 30 deletions
|
@ -88,7 +88,7 @@ them amounts to `/`-separating them in a URL.
|
||||||
These 5 combinators are very similar except that they each describe a
|
These 5 combinators are very similar except that they each describe a
|
||||||
different HTTP method. This is how they're declared
|
different HTTP method. This is how they're declared
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data Delete (contentTypes :: [*]) a
|
data Delete (contentTypes :: [*]) a
|
||||||
data Get (contentTypes :: [*]) a
|
data Get (contentTypes :: [*]) a
|
||||||
data Patch (contentTypes :: [*]) a
|
data Patch (contentTypes :: [*]) a
|
||||||
|
@ -116,7 +116,7 @@ The `Capture` combinator in servant takes a (type-level) string representing
|
||||||
the "name of the variable" and a type, which indicates the type we want to
|
the "name of the variable" and a type, which indicates the type we want to
|
||||||
decode the "captured value" to.
|
decode the "captured value" to.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data Capture (s :: Symbol) a
|
data Capture (s :: Symbol) a
|
||||||
-- s :: Symbol just says that 's' must be a type-level string.
|
-- s :: Symbol just says that 's' must be a type-level string.
|
||||||
```
|
```
|
||||||
|
@ -153,7 +153,7 @@ active users whereas `/users` would list them all.
|
||||||
|
|
||||||
Here are the corresponding data type declarations:
|
Here are the corresponding data type declarations:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data QueryParam (sym :: Symbol) a
|
data QueryParam (sym :: Symbol) a
|
||||||
data QueryParams (sym :: Symbol) a
|
data QueryParams (sym :: Symbol) a
|
||||||
data QueryFlag (sym :: Symbol)
|
data QueryFlag (sym :: Symbol)
|
||||||
|
@ -171,7 +171,7 @@ after *January 1st, 2005*.
|
||||||
|
|
||||||
Corresponding data type declarations below.
|
Corresponding data type declarations below.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data MatrixParam (sym :: Symbol) a
|
data MatrixParam (sym :: Symbol) a
|
||||||
data MatrixParams (sym :: Symbol) a
|
data MatrixParams (sym :: Symbol) a
|
||||||
data MatrixFlag (sym :: Symbol)
|
data MatrixFlag (sym :: Symbol)
|
||||||
|
@ -206,7 +206,7 @@ Request` or `Unsupported Content Type` as appropriate.
|
||||||
|
|
||||||
Here's the data type declaration for it:
|
Here's the data type declaration for it:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data ReqBody (contentTypes :: [*]) a
|
data ReqBody (contentTypes :: [*]) a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ The `Header` combinator in servant takes a type-level string for the header
|
||||||
name and the type to which we want to decode the header's value (from some
|
name and the type to which we want to decode the header's value (from some
|
||||||
textual representation), as illustrated below:
|
textual representation), as illustrated below:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data Header (sym :: Symbol) a
|
data Header (sym :: Symbol) a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ headers too. *servant* provides a `Headers` combinator that carries a list of
|
||||||
`Header` and can be used by simply wrapping the "return type" of an endpoint
|
`Header` and can be used by simply wrapping the "return type" of an endpoint
|
||||||
with it.
|
with it.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data Headers (ls :: [*]) a
|
data Headers (ls :: [*]) a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ Each function makes available as an argument any value that the response may dep
|
||||||
|
|
||||||
As you can see in the code above, we just "pattern match our way" to these functions. If we try to derive less or more functions than there are endpoints in the API, we obviously get an error. The `BaseUrl` value there is just:
|
As you can see in the code above, we just "pattern match our way" to these functions. If we try to derive less or more functions than there are endpoints in the API, we obviously get an error. The `BaseUrl` value there is just:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
-- | URI scheme to use
|
-- | URI scheme to use
|
||||||
data Scheme =
|
data Scheme =
|
||||||
Http -- ^ http://
|
Http -- ^ http://
|
||||||
|
|
|
@ -26,5 +26,5 @@ convert =
|
||||||
go :: [String] -> [String]
|
go :: [String] -> [String]
|
||||||
go (a : r)
|
go (a : r)
|
||||||
| ">" `isPrefixOf` a
|
| ">" `isPrefixOf` a
|
||||||
= "``` haskell" : map (drop 2) (a : r) ++ "```" : []
|
= "``` haskell ignore" : map (drop 2) (a : r) ++ "```" : []
|
||||||
go x = x
|
go x = x
|
||||||
|
|
|
@ -94,7 +94,7 @@ With all of this, we can derive docs for our API.
|
||||||
|
|
||||||
*servant*'s markdown pretty printer is a function named `markdown`.
|
*servant*'s markdown pretty printer is a function named `markdown`.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
markdown :: API -> String
|
markdown :: API -> String
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ need to have some language extensions and imports:
|
||||||
> import qualified Data.Aeson.Parser
|
> import qualified Data.Aeson.Parser
|
||||||
> import qualified Text.Blaze.Html
|
> import qualified Text.Blaze.Html
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ Nothing funny going on here. But we now can define our list of two users.
|
||||||
|
|
||||||
Let's also write our API type.
|
Let's also write our API type.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
type UserAPI1 = "users" :> Get '[JSON] [User]
|
type UserAPI1 = "users" :> Get '[JSON] [User]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ decided to provide a pair of typeclasses, `FromText` and `ToText` which just
|
||||||
let you say that you can respectively *extract* or *encode* values of some type
|
let you say that you can respectively *extract* or *encode* values of some type
|
||||||
*from*/*to* text. Here are the definitions:
|
*from*/*to* text. Here are the definitions:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
class FromText a where
|
class FromText a where
|
||||||
fromText :: Text -> Maybe a
|
fromText :: Text -> Maybe a
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ your own.
|
||||||
|
|
||||||
or writing the instances by hand:
|
or writing the instances by hand:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
instance FromText UserId where
|
instance FromText UserId where
|
||||||
fromText = fmap UserId fromText
|
fromText = fmap UserId fromText
|
||||||
|
|
||||||
|
@ -394,7 +394,7 @@ The truth behind `JSON`
|
||||||
What exactly is `JSON`? Like the 3 other content types provided out of the box
|
What exactly is `JSON`? Like the 3 other content types provided out of the box
|
||||||
by *servant*, it's a really dumb data type.
|
by *servant*, it's a really dumb data type.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data JSON
|
data JSON
|
||||||
data PlainText
|
data PlainText
|
||||||
data FormUrlEncoded
|
data FormUrlEncoded
|
||||||
|
@ -415,7 +415,7 @@ haddocks from this link, you can see that we just have to specify
|
||||||
use `(//) :: ByteString -> ByteString -> MediaType`. The precise way to specify
|
use `(//) :: ByteString -> ByteString -> MediaType`. The precise way to specify
|
||||||
the `MediaType` is to write an instance for the `Accept` class:
|
the `MediaType` is to write an instance for the `Accept` class:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
-- for reference:
|
-- for reference:
|
||||||
class Accept ctype where
|
class Accept ctype where
|
||||||
contentType :: Proxy ctype -> MediaType
|
contentType :: Proxy ctype -> MediaType
|
||||||
|
@ -428,7 +428,7 @@ The second step is centered around the `MimeRender` and `MimeUnrender` classes.
|
||||||
These classes just let you specify a way to respectively encode and decode
|
These classes just let you specify a way to respectively encode and decode
|
||||||
values respectively into or from your content-type's representation.
|
values respectively into or from your content-type's representation.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
class Accept ctype => MimeRender ctype a where
|
class Accept ctype => MimeRender ctype a where
|
||||||
mimeRender :: Proxy ctype -> a -> ByteString
|
mimeRender :: Proxy ctype -> a -> ByteString
|
||||||
-- alternatively readable as:
|
-- alternatively readable as:
|
||||||
|
@ -442,7 +442,7 @@ In the case of `JSON`, this is easily dealt with! For any type `a` with a
|
||||||
`ToJSON` instance, we can render values of that type to JSON using
|
`ToJSON` instance, we can render values of that type to JSON using
|
||||||
`Data.Aeson.encode`.
|
`Data.Aeson.encode`.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
instance ToJSON a => MimeRender JSON a where
|
instance ToJSON a => MimeRender JSON a where
|
||||||
mimeRender _ = encode
|
mimeRender _ = encode
|
||||||
```
|
```
|
||||||
|
@ -450,7 +450,7 @@ instance ToJSON a => MimeRender JSON a where
|
||||||
And now the `MimeUnrender` class, which lets us extract values from lazy
|
And now the `MimeUnrender` class, which lets us extract values from lazy
|
||||||
`ByteString`s, alternatively failing with an error string.
|
`ByteString`s, alternatively failing with an error string.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
class Accept ctype => MimeUnrender ctype a where
|
class Accept ctype => MimeUnrender ctype a where
|
||||||
mimeUnrender :: Proxy ctype -> ByteString -> Either String a
|
mimeUnrender :: Proxy ctype -> ByteString -> Either String a
|
||||||
-- alternatively:
|
-- alternatively:
|
||||||
|
@ -471,7 +471,7 @@ you are curious.
|
||||||
|
|
||||||
This function is exactly what we need for our `MimeUnrender` instance.
|
This function is exactly what we need for our `MimeUnrender` instance.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
instance FromJSON a => MimeUnrender JSON a where
|
instance FromJSON a => MimeUnrender JSON a where
|
||||||
mimeUnrender _ = eitherDecodeLenient
|
mimeUnrender _ = eitherDecodeLenient
|
||||||
```
|
```
|
||||||
|
@ -627,7 +627,7 @@ as interfaces to databases that we interact with in `IO`;
|
||||||
|
|
||||||
Let's recall some definitions.
|
Let's recall some definitions.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
-- from the Prelude
|
-- from the Prelude
|
||||||
data Either e a = Left e | Right a
|
data Either e a = Left e | Right a
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ action that either returns an error or a result.
|
||||||
The aforementioned `either` package is worth taking a look at. Perhaps most
|
The aforementioned `either` package is worth taking a look at. Perhaps most
|
||||||
importantly:
|
importantly:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
left :: Monad m => e -> EitherT e m a
|
left :: Monad m => e -> EitherT e m a
|
||||||
```
|
```
|
||||||
Allows you to return an error from your handler (whereas `return` is enough to
|
Allows you to return an error from your handler (whereas `return` is enough to
|
||||||
|
@ -659,7 +659,7 @@ Performing IO
|
||||||
|
|
||||||
Another important instance from the list above is `MonadIO m => MonadIO (EitherT e m)`. [`MonadIO`](http://hackage.haskell.org/package/transformers-0.4.3.0/docs/Control-Monad-IO-Class.html) is a class from the *transformers* package defined as:
|
Another important instance from the list above is `MonadIO m => MonadIO (EitherT e m)`. [`MonadIO`](http://hackage.haskell.org/package/transformers-0.4.3.0/docs/Control-Monad-IO-Class.html) is a class from the *transformers* package defined as:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
class Monad m => MonadIO m where
|
class Monad m => MonadIO m where
|
||||||
liftIO :: IO a -> m a
|
liftIO :: IO a -> m a
|
||||||
```
|
```
|
||||||
|
@ -688,7 +688,7 @@ error message, all you have to do is use the `left` function mentioned above
|
||||||
and provide it with the appropriate value of type `ServantErr`, which is
|
and provide it with the appropriate value of type `ServantErr`, which is
|
||||||
defined as:
|
defined as:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
data ServantErr = ServantErr
|
data ServantErr = ServantErr
|
||||||
{ errHTTPCode :: Int
|
{ errHTTPCode :: Int
|
||||||
, errReasonPhrase :: String
|
, errReasonPhrase :: String
|
||||||
|
@ -773,7 +773,7 @@ under some path in your web API. As mentioned earlier in this document, the
|
||||||
application". Well, servant-server provides a function to get a file and
|
application". Well, servant-server provides a function to get a file and
|
||||||
directory serving WAI application, namely:
|
directory serving WAI application, namely:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
-- exported by Servant and Servant.Server
|
-- exported by Servant and Servant.Server
|
||||||
serveDirectory :: FilePath -> Server Raw
|
serveDirectory :: FilePath -> Server Raw
|
||||||
```
|
```
|
||||||
|
@ -809,7 +809,7 @@ In other words:
|
||||||
|
|
||||||
Here is our little server in action.
|
Here is our little server in action.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
$ curl http://localhost:8081/code/T1.hs
|
$ curl http://localhost:8081/code/T1.hs
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
@ -918,7 +918,7 @@ We can instead factor out the `userid`:
|
||||||
|
|
||||||
However, you have to be aware that this has an effect on the type of the corresponding `Server`:
|
However, you have to be aware that this has an effect on the type of the corresponding `Server`:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
Server UserAPI3 = (Int -> EitherT ServantErr IO User)
|
Server UserAPI3 = (Int -> EitherT ServantErr IO User)
|
||||||
:<|> (Int -> EitherT ServantErr IO ())
|
:<|> (Int -> EitherT ServantErr IO ())
|
||||||
|
|
||||||
|
@ -1076,7 +1076,7 @@ Using another monad for your handlers
|
||||||
|
|
||||||
Remember how `Server` turns combinators for HTTP methods into `EitherT ServantErr IO`? Well, actually, there's more to that. `Server` is actually a simple type synonym.
|
Remember how `Server` turns combinators for HTTP methods into `EitherT ServantErr IO`? Well, actually, there's more to that. `Server` is actually a simple type synonym.
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
type Server api = ServerT api (EitherT ServantErr IO)
|
type Server api = ServerT api (EitherT ServantErr IO)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1090,7 +1090,7 @@ Natural transformations
|
||||||
If we have a function that gets us from an `m a` to an `n a`, for any `a`, what
|
If we have a function that gets us from an `m a` to an `n a`, for any `a`, what
|
||||||
do we have?
|
do we have?
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
newtype m :~> n = Nat { unNat :: forall a. m a -> n a}
|
newtype m :~> n = Nat { unNat :: forall a. m a -> n a}
|
||||||
|
|
||||||
-- For example
|
-- For example
|
||||||
|
@ -1103,7 +1103,7 @@ So if you want to write handlers using another monad/type than `EitherT
|
||||||
ServantErr IO`, say the `Reader String` monad, the first thing you have to
|
ServantErr IO`, say the `Reader String` monad, the first thing you have to
|
||||||
prepare is a function:
|
prepare is a function:
|
||||||
|
|
||||||
``` haskell
|
``` haskell ignore
|
||||||
readerToEither :: Reader String :~> EitherT ServantErr IO
|
readerToEither :: Reader String :~> EitherT ServantErr IO
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue