I'm using an openapi-based library within a handler; unfortunately it throws a lot of network or http exceptions, so I'm attempting to use Control.Monad.CatchIO with it, but banging my head against the types.
This is where I'm at:
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Control.Exception as E
import qualified Control.Monad.CatchIO as CI (try,MonadCatchIO)
import Control.Monad.State
import Snap
import Application
import Services
import qualified Helper.Heist as H
import Snap.AzureAdAuth
-- this is the function that throws the exceptions
runQuery :: (Produces req accept, MimeUnrender accept b1, Show b1, MimeType contentType) => ServicesRequest req contentType b1 accept -> Handler App (AuthManager App) (Either MimeError b1)
runQuery r = ...
runQuery' :: forall req accept contentType b1. (Produces req accept, MimeUnrender accept b1, Show b1, MimeType contentType)
=> ServicesRequest req contentType b1 accept
-> Handler App (AuthManager App) (Either E.SomeException (Either MimeError b1))
runQuery' req =
CI.try $ runQuery req :: Handler App (AuthManager App) (Either E.SomeException (Either MimeError b1))
Compiling gives this error message:
* Could not deduce (CI.MonadCatchIO
(Handler App (AuthManager App)))
arising from a use of `CI.try'
from the context: (Produces req accept, MimeUnrender accept b1,
Show b1, MimeType contentType)
bound by the type signature for:
runQuery' :: forall req accept contentType b1.
(Produces req accept, MimeUnrender accept b1, Show b1,
MimeType contentType) =>
ServicesRequest req contentType b1 accept
-> Handler
App
(AuthManager App)
(Either E.SomeException (Either MimeError b1))
at src/Helper/API.hs:(96,1)-(99,102)
* In the expression: CI.try $ runQuery req
In an equation for runQuery':
runQuery' req = CI.try $ runQuery req
Any thoughts on how to line up the types?
I can't reproduce your example exactly, because there are still many types for which I don't know where they're coming from.
The Snap framework's Handler
monad uses MonadBaseControl
to embed the IO
monad, rather than the more traditional mtl-style MonadIO
and MonadCatchIO
that MonadCatchIO-mtl
uses.
Instead, the lifted-base
package provides primitives such as try
(in Control.Exception.Lifted
) for these embeddings.
The following code compiles for me:
import Snap.Snaplet
import Control.Exception.Lifted hiding (Handler)
runQuery :: Handler a b c
runQuery = undefined
runQuery' :: (Exception e) => Handler a b (Either e a1)
runQuery' = try runQuery
Happy Haskelling!