Proposal: Add throwSTM and generalize catchSTM

Bas van Dijk v.dijk.bas at gmail.com
Mon Sep 27 17:47:39 EDT 2010


On Sun, Sep 26, 2010 at 11:24 PM, Antoine Latter <aslatter at gmail.com> wrote:
> So that's a +1 from me. It would be nice to get a Hackage analysis to
> get an idea of what will break from this change.

There are 83 direct reverse dependencies of stm:

http://bifunctor.homelinux.net/~roel/cgi-bin/hackage-scripts/revdeps/stm-2.1.2.2#direct

None of them define throwSTM, so adding this function will not break anything.

6 of those packages use catchSTM.

>From a quick read of the source code all of them seem to keep working
with the proposed generalization.

What follows is the detailed analysis:


* stm-io-hooks-0.6.0/Control/Concurrent/AdvSTM.hs:88:

import qualified Control.Concurrent.STM as S

class Monad m => MonadAdvSTM m where
    ...
    catchSTM  :: Exception e => m a -> (e -> m a) -> m a

instance MonadAdvSTM AdvSTM where
    ...
    catchSTM action handler = do
        action'  <- unlift action
        handler' <- unlift1 handler
        let handler'' e = case fromException e of
                            Nothing -> throw e
                            Just e' -> handler' e'
        liftAdv $ S.catchSTM action' handler''

This code does not have to be modified.
However there's an opportunity to simplify it to just:

    catchSTM action handler = do
        action'  <- unlift action
        handler' <- unlift1 handler
        liftAdv $ S.catchSTM action' handler'


* HAppS-State-0.9.3/src/HAppS/State/Monad.hs:86:
* happstack-state-0.5.0.2/src/Happstack/State/Monad.hs:82:

class CatchEv m where
#if __GLASGOW_HASKELL__ < 610
    catchEv :: Ev m a -> (Exception -> a) -> Ev m a
#else
    catchEv :: Ev m a -> (SomeException -> a) -> Ev m a
#endif
instance CatchEv (ReaderT st STM) where
    catchEv (Ev cmd) fun = Ev $ \s -> ReaderT $ \r -> runReaderT (cmd
s) r `catchSTM` (\a -> return (fun a))

instance CatchEv (StateT st STM) where
    catchEv (Ev cmd) fun = Ev $ \s -> StateT $ \r -> runStateT (cmd s)
r `catchSTM` (\a -> return (fun a,r))

This code does not have to be modified.
However it would be a nice opportunity to generalize:
catchEv ::  Exception e => Ev m a -> (e -> a) -> Ev m a


* PriorityChansConverger-0.1/Control/Concurrent/ConcurrentUISupport.hs:223:

reportExceptionIfAnySTM :: (String -> STM ()) -> String -> STM a -> STM a
reportExceptionIfAnySTM reportStr caller_f_name stma = catchSTM stma
(\ se@(E.SomeException e) -> reportStr ("An error occurred in function
'" ++ caller_f_name ++ "'. Type: " ++ (show $ typeRepTyCon $ typeOf e)
++ ". Representation: " ++ show se) >> E.throw (se ::
E.SomeException))

This code does not have to be modified.


* Pugs-6.2.13.15/src/Pugs/AST/Eval.hs:181:

guardSTM :: STM a -> Eval a
guardSTM x = do
    rv <- stm $ fmap Right x `catchSTM` (return . Left)
    case rv of
        Left e -> fail (show e)
        Right v -> return v

This code does not have to be modified.


* monadIO-0.9.2.0/src/Control/Concurrent/STM/MonadIO.hs:52:

Only reexports catchSTM. There's one package which depends on monadIO:
orc. However this package does not use the exported catchSTM.



Regards,

Bas


More information about the Libraries mailing list