2015-04-15 53 views
1

我正在使用API​​的servant库。它运行在:EitherT (Int, String) IO a monad中。我有一个类型IO Maybe a的功能,并且想要使用它。从IO Maybe a转换为EitherT IO a

这里有一个工作的例子:

sourcesGetAll :: EitherT (Int, String) IO [Source] 
sourcesGetAll = liftIO $ sourcesList h 

sourcesList :: IO [Source] 

但现在我要使用这两个功能结合在一起

sourcesFind :: IO (Maybe Source) 
sourcesGetOne :: EitherT (Int, String) IO Source 
sourcesGetOne = ??? 

我想做到这一点:

maybeNotFound :: Maybe a -> Either (Int, String) a 
maybeNotFound Nothing = Left (404, "Not Found") 
maybeNotFound Just a = Right a 

怎么办我是用所有花哨的单子做的?

回答

4

可以分解成两个独立的问题是:

  • 变换IO (Maybe a)MaybeT IO a

  • 变换MaybeT IO aEitherT (Int, String) a

第一种是通过使用MaybeT构造解决:

noteT :: Monad m => a -> MaybeT m b -> EitherT a m b 
+0

我想既然是切换到ExceptT而不是EitherT这不会以'错误2.0'工作? – bennofs

+1

正确。 'errors-2.0'将使用'ExceptT'而不是'EitherT' –

1

另一个答案感谢mpickering freenode上:

MaybeT :: IO (Maybe a) -> MaybeT IO a 

二是通过使用noteTerrors库解决:

sourcesGetOne = EitherT $ maybeNotFound <$> sourcesFind 

所以,问题是如何编写一个函数.. IO (Maybe a) -> EitherT (Int, String) IO a 给出一个函数f :: Maybe a -> Either (Int, String) a,再一个办法是..

myFunc action = EitherT (f <$> action)

如果你看一下文档的EitherT - https://hackage.haskell.org/package/either-4.3.3.2/docs/Control-Monad-Trans-Either.html。然后你会看到EitherT (Int, String) IO a,实际上只是一个包裹起来IO (Either (Int, String) a)