在ExceptT
Monad变换器堆栈中,throwE
之后的绑定表达式将无法执行。
{-# LANGUAGE
GeneralizedNewtypeDeriving
#-}
import Control.Monad.Except (MonadError (..), MonadIO, liftIO)
import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)
newtype MyTrans e a = MyTrans { unMyTrans :: ExceptT e IO a }
deriving (Functor, Applicative, Monad, MonadIO, MonadError e)
throwMT :: e -> MyTrans e a
throwMT = MyTrans . throwE
runMyTrans :: MyTrans e a -> IO (Either e a)
runMyTrans = runExceptT . unMyTrans
comp = do
liftIO $ putStrLn "Starting Computation"
throwMT "Some Error"
-- dead code from this line
liftIO $ putStrLn "Ending Computation"
return ()
main = print =<< runMyTrans comp
答案 0 :(得分:3)
答案 1 :(得分:3)
让我们忽略MyTrans
新型噪音,然后看看
throwE x >>= f :: ExceptT e IO a
深入研究Control.Monad.Trans.Except
,我们看到了
newtype ExceptT e m a =
ExceptT {runExceptT :: m (Either e a)}
throwE :: Monad m => e -> ExceptT e m a
throwE e = ExceptT (pure (Left e))
instance Monad m => Monad (ExceptT e m) where
m >>= f = ExceptT $ do
res <- runExceptT m
case res of
Left e -> pure (Left e)
Right r -> runExceptT (f r)
内联这些(GHC喜欢做的事情),我们看到throwE e >>= f
是
ExceptT $ do
res <- pure (Left e)
case res of
Left e -> pure (Left e)
Right r -> runExceptT (f r)
考虑到这一点对于一个任意的monad,GHC不会再进一步,因为它不知道m
是一个守法的monad并且不会寻找& #34;自由定理&#34;这可能有所帮助。
但是,这不是一个任意的monad!这是IO
!
newtype IO a =
IO (State# RealWorld
-> (# State# RealWorld, a #))
unIO :: IO a -> State# RealWorld
-> (# State# RealWorld, a #)
unIO (IO f) = f
instance Monad IO where
return a = IO $ \s -> (# s, a #)
IO m >>= f = IO $ \s ->
case m s of
(# s', a #) -> unIO (f a) s'
左身份法可以被证明&#34;通过优化获得IO
。
return a >>= g
= inlining
IO $ \s ->
case (\t -> (# t, a #)) s of
(# s', r #) -> unIO (g r) s'
= beta reduction
IO $ \s ->
case (# s, a #) of
(# s', r #) -> unIO (g r) s'
= case of known constructor
IO $ \s -> unIO (g a) s
= (assuming g has arity at least two, which it will here)
g a
应用此信息,throwE e >>= f
变为
ExceptT $
(\res -> case res of
Left e -> pure (Left e)
Right r -> runExceptT (f r)) (Left e)
Beta减少并应用已知构造函数的情况
ExceptT $ pure (Left e)
完全消除了死密码。