我有2个具有“交叉”接口的功能:
type Config = (param1, param2)
runExe :: [String] -> ReaderT Config IO ExitCode
someAction :: [String] -> ReaderT Config (MaybeT IO) ()
由于runExe
和someAction
都带有不可变的Config,我想隐式传递它而不明确地“询问”。如下所示:
someAction params = monadConvertor runExe ["some" , "params"]
如何实施monadConvertor
?
据我所知,monadConvertor需要提取IO ExitCode然后解除guard (rc == ExitSuccess)
。但我不知道是否有可能。
答案 0 :(得分:4)
您的monadConverter
应具有以下类型:
monadConverter :: ReaderT Config IO ExitCode -> ReaderT Config (MaybeT IO) ()
正如您在问题中所写的那样,您只需要“提取”ExitCode
,然后“提升”guard (rc == ExitCode)
,您就可以使用lift
功能。现在的问题是您无法在ReaderT Config IO ExitCode
内使用ReaderT Config (MaybeT IO) ()
。您可以使用mapReaderT:
mapReaderT :: mapReaderT :: (m a -> n b) -> ReaderT r m a -> ReaderT r n b
使用该功能,monadReader
可以按如下方式实施:
monadConverter :: ReaderT Config IO ExitCode -> ReaderT Config (MaybeT IO) ()
monadConverter action = do
exitCode <- mapReaderT lift action
lift $ guard (exitCode == ExitSuccess)
此处,mapReaderT lift
的类型为ReaderT Config IO ExitCode -> ReaderT Config (MaybeT IO) ExitCode
。