为什么可以替换这些类型?
Why it it possible to replace these types?
有些事情似乎很不可思议:
foo :: a -> StateT Env (ReaderT Env (ErrorT String IO)) String
可以替换为
foo :: a -> ErrorT String IO String
怎么可能?毕竟是完全不同的类型...
显然,在所有 情况下不可能将它们相互替换。例如,如果您明确使用 ErrorT . return $ Left "Muahar"
,则此 必须 是 ErrorT String m a
.
但是,这两种类型都是 a -> M String
形式,带有一个 (transformer-stack) monad M
,它是 MonadIO
and MonadError String
的一个实例。因此,如果仅使用 liftIO ioaction
形式的操作定义此函数,并且可能使用 throwError
和 catchError
形式的操作,那么它将像这些 monad 中的任何一个一样工作。一般类型是
foo :: (MonadIO m, MonadError String m) => a -> m String
有些事情似乎很不可思议:
foo :: a -> StateT Env (ReaderT Env (ErrorT String IO)) String
可以替换为
foo :: a -> ErrorT String IO String
怎么可能?毕竟是完全不同的类型...
显然,在所有 情况下不可能将它们相互替换。例如,如果您明确使用 ErrorT . return $ Left "Muahar"
,则此 必须 是 ErrorT String m a
.
但是,这两种类型都是 a -> M String
形式,带有一个 (transformer-stack) monad M
,它是 MonadIO
and MonadError String
的一个实例。因此,如果仅使用 liftIO ioaction
形式的操作定义此函数,并且可能使用 throwError
和 catchError
形式的操作,那么它将像这些 monad 中的任何一个一样工作。一般类型是
foo :: (MonadIO m, MonadError String m) => a -> m String