2014-05-17 30 views
3

我有2个功能与“相交”接口:如何结合不同的Monad堆栈?

type Config = (param1, param2) 

runExe :: [String] -> ReaderT Config IO ExitCode 
someAction :: [String] -> ReaderT Config (MaybeT IO)() 

由于两个runExesomeAction携带一成不变的配置,我想通过它含蓄而不做“要求”明确。类似如下:

someAction params = monadConvertor runExe ["some" , "params"] 

我该如何实施monadConvertor

据我所知,monadConvertor需要提取IO ExitCode然后解除guard (rc == ExitSuccess)。但我不知道是否有可能。

回答

4

monadConverter应具有以下类型:

monadConverter :: ReaderT Config IO ExitCode -> ReaderT Config (MaybeT IO)() 

正如你已经在你的问题中写道,你只需要在“解压”的ExitCode,然后“升降机” guard (rc == ExitCode),您可以用做lift功能。现在的问题是,你不能在ReaderT Config (MaybeT IO)()内使用ReaderT Config IO ExitCode。您可以通过使用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

+0

是的,它很好用)。但让我指出,在这种情况下,没有必要明确提防。 – kubivan