从 IO Maybe a 转换为 EitherT IO a
Convert from IO Maybe a to EitherT IO a
我正在为 API 使用 servant 库。它运行在:EitherT (Int, String) IO a
monad 中。我有一个类型为 IO Maybe 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
如何使用所有花哨的 monad 来做到这一点?
您可以使用 hoistEither :: Monad m => Either a b -> EitherT a m b
来实现:
maybeNotFoundT :: IO (Maybe a) -> EitherT (Int, String) IO a
maybeNotFoundT maAct = do
ma <- liftIO maAct -- get the Maybe a. Now ma :: Maybe a
hoistEither $ maybeNotFound ma
您可以将其分解为两个独立的问题:
将IO (Maybe a)
转化为MaybeT IO a
将MaybeT IO a
转化为EitherT (Int, String) a
第一个使用MaybeT
构造函数解决:
MaybeT :: IO (Maybe a) -> MaybeT IO a
第二个是使用 errors
库中的 noteT
解决的:
noteT :: Monad m => a -> MaybeT m b -> EitherT a m b
感谢 freenode 上的 mpickering 的另一个答案:
sourcesGetOne = EitherT $ maybeNotFound <$> sourcesFind
So the question is how to write a function.. IO (Maybe a) -> EitherT (Int, String) IO a
Given a function f :: Maybe a -> Either (Int, String) a
, then one way is..
myFunc action = EitherT (f <$> action)
If you look at the docs for EitherT -- https://hackage.haskell.org/package/either-4.3.3.2/docs/Control-Monad-Trans-Either.html. Then you'll see that EitherT (Int, String) IO a
, is actually just a wrapped up IO (Either (Int, String) a)
我正在为 API 使用 servant 库。它运行在:EitherT (Int, String) IO a
monad 中。我有一个类型为 IO Maybe 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
如何使用所有花哨的 monad 来做到这一点?
您可以使用 hoistEither :: Monad m => Either a b -> EitherT a m b
来实现:
maybeNotFoundT :: IO (Maybe a) -> EitherT (Int, String) IO a
maybeNotFoundT maAct = do
ma <- liftIO maAct -- get the Maybe a. Now ma :: Maybe a
hoistEither $ maybeNotFound ma
您可以将其分解为两个独立的问题:
将
IO (Maybe a)
转化为MaybeT IO a
将
MaybeT IO a
转化为EitherT (Int, String) a
第一个使用MaybeT
构造函数解决:
MaybeT :: IO (Maybe a) -> MaybeT IO a
第二个是使用 errors
库中的 noteT
解决的:
noteT :: Monad m => a -> MaybeT m b -> EitherT a m b
感谢 freenode 上的 mpickering 的另一个答案:
sourcesGetOne = EitherT $ maybeNotFound <$> sourcesFind
So the question is how to write a function..
IO (Maybe a) -> EitherT (Int, String) IO a
Given a functionf :: Maybe a -> Either (Int, String) a
, then one way is..
myFunc action = EitherT (f <$> action)
If you look at the docs for EitherT -- https://hackage.haskell.org/package/either-4.3.3.2/docs/Control-Monad-Trans-Either.html. Then you'll see that
EitherT (Int, String) IO a
, is actually just a wrapped upIO (Either (Int, String) a)