输入runErrorT的签名

时间:2014-07-17 12:56:14

标签: haskell

我有一个函数,目标说,它需要一个类型为

的参数
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

2 个答案:

答案 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

但是,我不知道它有多么有价值。