@polecat Та вроде разобрался уже.
Вот черновик вопроса:
```
I'm getting a little confused regarding error-handling problem. I have a small REST API done via Scotty Haskell web framework. I have a handler that looks like this:
jobStatusUpdatePost :: WebAction ()
jobStatusUpdatePost = do
-- validate input data etc.
scottyEither $ setJobState s jid newDesc
-- render response
The main part here is this piece: `scottyEither $ setJobState s jid newDesc`. What's happening is that I have a library function responsible for updating a job state:
setJobState :: IO (Either Text ())
I'm fine with it, it's independant of Scotty framework, it's clear what it does and what it returns. But I'm bothered with the fact that I have to put that "scottyEither" that does error-handling inside my scotty action:
scottyEither :: (Monad m, ScottyError e)
=> ActionT e m (Either e a)
-> ActionT e m a
scottyEither v = v >>= go
where
go (Left e) = raise e
go (Right a) = return a
So I wondered, how would I write such a function `setJobState` that:
1. wouldn't be dependent upon scotty web framework's details (not be scotty-specific)
2. would raise exception itself
3. be integrated with ActionT monad (which is why I can't just use `Control.Exception.throw`, sometimes I might want to actually catch it!)
```
Короче оказалось, что в Scotty есть вот этот код:
```
instance (ScottyError e, Monad m) => MonadError (ActionError e) (ActionT e m) where
throwError = ActionT . throwError
catchError (ActionT m) f = ActionT (catchError m (runAM . f))
```
то есть можно сделать, например, вот так:
```
setJobState :: (MonadIO m)
=> JobStateStorage -> JobId -> JobState
-> m ()
setJobState s jid state = do
_ <- runRedisThrowing (s ^. redisConn) $ do
R.set (getJobStateKey jid) (toStrictByteString (J.encode state))
return ()
runRedisThrowing :: MonadIO m
=> R.Connection
-> R.Redis (Either R.Reply b)
-> m b
runRedisThrowing conn act = do
r <- liftIO $ R.runRedis conn act
either (throw . RedisError) return r
```
И ловить вот так:
```
_ <- catchError (setJobState s jid newDesc) (\err -> do
liftIO $ print (showError err))
```
Косо, криво, через жопу, но хоть что-то.
Собственно, чего хотелось бы -- это чтоб через exceptions можно было сделать catch и получить мой Exception, но я так понял, в Scotty плохо сделали и так не получится.
@pxqr > Unfortunately, I don't know of any functional language I'd call popular. I think it's because they all have dumb names like LISP and Haskell.
Лол.
// что такое коды возврата в категории Hawk так и не понял, видимо слишком умный для этого