unitym-0.1.0.2: A monad type class shared between web services

Copyright(c) Brian Hurt 2017
LicenseBSD3
Maintainerbhurt42@gmail.com
Stabilityexperimental
PortabilityHaskell
Safe HaskellSafe
LanguageHaskell2010

Network.UnityM

Description

One of the nice things about WAI is that it allows us to combine multiple different server frameworks in a single web server- allowing us to use (for example) Yesod to develop the server-side rendered HTML part of the website, and Servant to develop the REST API part. But this gives rise to a desire to share code between the different frameworks. This is where UnityM comes in.

UnityM is a type class for monad transformer stacks for web servers. The assumption, in addition to being in some monad, is that we are responding to some HTTP request, and can thus assume three things:

  1. That we have read-only access to some global environment data, generally a structure of some sort.
  2. That the containing framework will catch all exceptions and convert them into 500 (internal server error) status codes. And that thus the low level code does not have to capture and handle exceptions, and that a workable way to return 500 would be to just throw an exception.
  3. That we have the ability to "short-circuit" the evaluation on errors, and return 403 (permission denied) status codes from the request.

The type class is a multi-parameter type class, with the first parameter being the type of the environment variable that can be gotten. This allows code to constrain this type with further type class constaints, and thus work with multiple different environments, for example:

  class HasFoo a where
      getFoo :: a -> Foo

  bar :: (Monad m, HasFoo c, UnityM c m) => Something -> m Whatever
  bar x = do
      myFoo <- getFoo <$> getContext
      ...

Note that this type class assumes the code is "low-level", away from the web request- buisness logic, database access, etc. And thus a rich API for different status responses is not needed. Only two error results are supported- the generic 500 Internal Server error, and the 403 Permission Denied error. The second is only supported so that access grants can be generalized. Error checking code that needs different status results should be written in a framework-specific way.

The different implementations of the unity monad are in separate projects, so you don't get unnecessary dependencies.

Synopsis

Documentation

class UnityM c m | m -> c where Source #

The Unity Monad type class.

For code that executes in multiple different web contexts.

Minimal complete definition

getContext, permissionDenied

Methods

getContext :: m c Source #

Get the context, the global read-only data object

permissionDenied :: Text -> m a Source #

Short circuit the request with a 403 (Forbidden) status.

Instances

(Monad m, UnityM c m, MonadTrans t) => UnityM c (t m) Source #

Support monad transformers on top of a Unity monad.

Methods

getContext :: t m c Source #

permissionDenied :: Text -> t m a Source #