Free Your Client... and Your Requests Will Follow
=================================================

`free-http` is an http-client based on Free Monads. `free-http` exposes a Free Monad to express standard http verbs as well as several backends to interpet programs written in the free monad using various http clients (currently: a pure client, an `http-client`-backed client, and a random client).

See [here](https://github.com/aaronlevin/free-http/blob/master/src/Network/HTTP/Client/Free/Examples.hs#L152) for an example.

To use free-http, simply:

1. Import Network.HTTP.Client.Free to use the library.
2. Choose your base request type by defining your own instance of the `RequestType` type family or importing one from an interpreter. E.g.

  ```
  data MyClient
  type instance RequestType MyClient = Request
  ```

  or

  ```
  import Network.HTTP.Free.Client.HttpClient (HttpClient)
  ```

3. Choose your base response type by defining your own instance of the `ResponseTYpe` type family or importing one from an interpreter. E.g.  

  ```
  type instance ResponseType MyClient = Response ByteString
  ```

  or

  ```
  import Network.HTTP.Free.Client.HttpClient (HttpClient)
  ```

4. Write a program in the 'FreeHttp MyClient m a' free monad.
5. Import an interpreter, such as 'HttpClient'

  ```
  import Network.HTTP.Free.Client.HttpClient
  ```

6. Run your program against the interpreter:

  ```
  runHttp (myProgram :: FreeHttp MyClient IO String)
  ```

## Design Choices

### `RequestType` and `ResponseType`

Haskell is fortunate to have several very well-designed http clients: [http-client](https://hackage.haskell.org/package/http-client-0.4.16/docs/Network-HTTP-Client.html), [wreq](http://www.serpentine.com/wreq/), [http-conduit](https://hackage.haskell.org/package/http-conduit), [pipes-http](https://hackage.haskell.org/package/pipes-http), etc. Unfortunately, a few of those clients support several different *Request* and *Response* types. To keep `free-http` flexible, we use two type families defined as:

```
type family RequestType client  :: *
type family ResponseType client :: *
```

Our `HttpF` functor is thus defined as:

```
data HttpF client a = HttpF StdMethod (RequestType client) (ResponseType client -> a)
                    deriving Functor
```

This allows our `HttpF` functor to be agnostic of the foundational request and response type, while allowing interpreter authors to specify the concrete types they need for their http client libraries (e.g. `Request` in the case of `http-client`). A consequence of this is that `free-http` clients (you) need to specify, at some point, the foundation you're using. This can be done in two ways:

1. You can define your own foundation (see above).
2. You can import one from an interpreter.

To specify your request and response foundation, use replace the `client` type in `HttpF client a` or `FreeHttp client m a` to the type signalling your foundation. For example, the http-client, pure, and arbitrary interpreters use `HttpClient`, `PureClient`, and `ArbitraryClient` respectively.