Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define kind ResponseState and annoate res with kind ResponseState -> Type #85

Open
JordanMartinez opened this issue Aug 6, 2019 · 0 comments

Comments

@JordanMartinez
Copy link
Contributor

The res type in Conn is implicitly Type -> Type despite its declaration not showing that.

module Hyper.Conn where

-- | A `Conn` models the entirety of an HTTP connection, containing the fields
-- | `request`, `response`, and the extensibility point `components`.
type Conn req res components =
  { request :: req
  , response :: res -- (res :: Type -> Type)
  , components :: components
  }

This isn't immediately clear to the end-reader (unless one reads through the source code or potentially the docs). Moreover, the lack of using a kind here also allows one to use other non-ResponseState types here (e.g. res Int rather than res StatusLineOpen).

I propose we instead define a kind and more clearly indicate that. When I worked on implementing this, I found that the code is easier if the Conn type also has a type parameter for the responseState that it applies to res in its definition. In other words...

module Hyper.Conn where

-- | Defines the states of an HTTP request stream. It tracks whether or not
-- | some content has already been written to an HTTP request stream.
-- |
-- | Proper order of computations. Items marked with an asterisk indicate that
-- | transitioning back to the same state is valid:
-- | StatusLineOpen -> HeadersOpen* -> BodyOpen* -> ResponseEnded
foreign import kind ResponseState

-- | Type indicating that the status-line is ready to be
-- | sent.
foreign import data StatusLineOpen :: ResponseState

-- | Type indicating that headers are ready to be
-- | sent, i.e. the body streaming has not been started.
foreign import data HeadersOpen :: ResponseState

-- | Type indicating that headers have already been
-- | sent, and that the body is currently streaming.
foreign import data BodyOpen :: ResponseState

-- | Type indicating that headers have already been
-- | sent, and that the body stream, and thus the response,
-- | is finished.
foreign import data ResponseEnded :: ResponseState

-- | A `Conn` models the entirety of an HTTP connection, containing the fields
-- | `request`, `response`, and the extensibility point `components`.
type Conn request response components (responseState :: ResponseState) =
  { request :: request
  , response :: response responseState
  , components :: components
  }

-- now the `ResponseTransition` type alias is defined like so:
-- | A middleware transitioning from one `Response` state to another.
type ResponseStateTransition m (res :: ResponseState -> Type) (from :: ResponseState) (to :: ResponseState) =
  forall req comp.
  Middleware
  m
  (Conn req res comp from)
  (Conn req res comp to)
  Unit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
1 participant