Skip to content

Instantly share code, notes, and snippets.

@arthurxavierx
Created July 29, 2020 13:28
Show Gist options
  • Save arthurxavierx/5e2dafad3c14431442c52746e2e51838 to your computer and use it in GitHub Desktop.
Save arthurxavierx/5e2dafad3c14431442c52746e2e51838 to your computer and use it in GitHub Desktop.
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
-- | This type class describes operations that can be performed over Servant
-- API trees. The instances essentially distribute the actions over the ':<|>'
-- constructor, and apply them to the leaves of the API trees: functions or
-- values in an applicative functor.
class ServantApi m api | api -> m where
-- | Embeds an applicative action in a servant API, such that in each of API's
-- leaves, the given action is sequenced *before* the actual API endpoint.
--
-- This can be useful for inserting dynamic precondition checks in APIs.
before :: Applicative m => m x -> api -> api
-- | Embeds an applicative action in a servant API, such that in each of API's
-- leaves, the given action is sequenced *after* the actual API endpoint.
--
-- This can be useful for appending dynamic postcondition checks to APIs.
after :: Applicative m => m x -> api -> api
-- | Short-circuit all of the API's leaves to return the specified value
-- instead of performing any other actions.
--
-- This can be used for producing errors in APIs when a static check fails.
override :: (forall x. m x) -> api
instance (ServantApi m l, ServantApi m r) => ServantApi m (l :<|> r) where
before m (l :<|> r) = before m l :<|> before m r
after m (l :<|> r) = after m l :<|> after m r
override m = override m :<|> override m
instance ServantApi m f => ServantApi m (b -> f) where
before m f b = before m (f b)
after m f b = after m (f b)
override m _ = override m
instance Applicative m => ServantApi m (m a) where
before m ma = m *> ma
after m ma = const <$> ma <*> m
override = id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment