我有一个函数,目标说,它需要一个类型为
的参数target :: Action m UserId -> something
其中m是任何monad。
我从现有函数中获取参数,将其命名为" func"
func :: something -> Action m UserId
我希望改装一个ErrorT变换器
func :: something -> ErrorT String (Action m) UserId
当我在func上使用runErrorT以提取成功/失败的结果时,我当然得到类型
的结果Action m (Either String UserId)
即。表示成功或失败的任一个都嵌入在周围的monad中。这对某些目的很有用,例如在Action monad的上下文中测试左和右。
我真正需要的是返回的runErrorT版本 字符串(Action m UserId)
因为那样我就可以使用正确的值并使用它。在这种情况下我该怎么办?或者有一种聪明的重新调整方式
Action m (Either String UserId) -> Either String (Action m UserId)
但我无法访问必要的构造函数
UserId -> Action m UserId
因为它恰好是Action本身就是一个转换器
type Action = ReaderT MongoDBContext
答案 0 :(得分:2)
我们说你有
func :: a -> ErrorT String (Action m) UserId
target :: Action m UserId -> b
然后
run :: a -> Action m (Either String b)
run a = do
result <- runErrorT $ func a
return $ case result of
Left str -> Left str
Right uid -> Right $ target (return uid)
或者更简洁
run = runErrorT . fmap (target . return) . func
答案 1 :(得分:2)
一般而言,如果不了解具体的m
,就无法做到这一点。例如,这不是IO (Either String Int) -> Either String (IO Int)
类型的函数,它不使用unsafePerformIO
或类似的东西。
你可以写下类似的内容:
dupNoEx :: IO (Either String Int) -> IO (Either String (IO Int))
dupNoEx act = do
ev <- act
case v of
Left s -> return $ Left s
Right i -> return . Right $ return i
但是,我不知道它有多么有价值。