🚨 WORK IN PROGRESS 🚨
A Graded Monad 𝐺 maps from a Monoidal Category (𝔼, ⊗, Iₑ) to the
Category of Endofunctors: 𝐺 : 𝔼 → [ℂ, ℂ].
Graded Monads give you two monad-like operations:
η : Id → G Iₑ
μ : 𝐺 x ∘ 𝐺 y → 𝐺 (x ⊗ y)
Which capture, or 'grades', the monad with objects of 𝔼.
This library encodes graded monads in Haskell for managing effects
using a QualifiedDo interface:
type GradedMonad ::
([Type] -> Type -> Type) ->
Type ->
(Type -> Type -> Type) ->
Constraint
class (FunctorF m) => GradedMonad m i t | m -> i t where
{-# MINIMAL greturn, (gjoin | gbind) #-}
greturn :: Identity ~> m '[]
gjoin :: (AppendTensored xs) => (m xs `Compose` m ys) ~> m (xs ++ ys)
gjoin (Compose m) = m `gbind` id
gbind :: (AppendTensored xs) => m xs a -> (a -> m ys b) -> m (xs ++ ys) b
gbind mxa f = gjoin $ Compose $ fmap f mxaWe currently have graded version of ExceptT and WriterT.
The graded form of ExceptT allows you to track specify specific
error types per subroutine and tensor those error types together when
performaing a graded bind:
mkRequest :: (GradedMonadError m) => String -> m '[ParseError] Request
mkRequest _ = G.return Request
transformRequest :: (GradedMonadError m) => Request -> m '[TransformError] Request
transformRequest _ = gthrowError TransformError
invokeRequest _ = G.return Response
main :: IO ()
main = do
result <- runExceptT' $ G.do
req <- mkRequest "hoogle.hackage.com"
req' <- transformRequest req
invokeRequest req'
case result of
Left (Left ParseError) -> print ParseError
Left (Right (Left TransformError)) -> print TransformError
Left (Right (Right HttpError)) -> print HttpError
Right Response -> print ResponseThe graded form of WriterT allows you to specifiy unique log types per subroutine in a similar manner:
mkRequest :: (GradedMonadWriter m) => String -> m '[ParseLog] Request
mkRequest _ = G.do
gtell ParseLog
G.return Request
transformRequest :: (GradedMonadWriter m) => Request -> m '[TransformLog] Request
transformRequest _ = G.do
gtell TransformLog
G.return Request
invokeRequest :: (GradedMonadWriter m) => Request -> m '[HttpLog] Response
invokeRequest _ = G.do
gtell HttpLog
G.return Response
main :: IO ()
main = do
result <- runWriterT' $ G.do
req <- mkRequest "hoogle.hackage.com"
req' <- transformRequest req
invokeRequest req'
-- result :: (Response, Tensored (,) () '[ParseLog, TransformLog, HttpLog])
print result