如何使用bind与嵌套monads? [英] How to use bind with nested monads?
问题描述
我有两个函数,一个试图从web服务获取令牌并可能失败,另一个尝试使用此令牌获取用户名并可能失败。
getToken :: IO(可能令牌)
getUsername :: Token - > IO(Maybe String)
我想将getToken的结果提供给 getUsername
。如果只有 IO
或 Maybe
,我可以简单地使用bind,但由于存在嵌套的monads,所以我可以T。我怎样才能写出一些相当于 getToken>> = getUsername :: IO(Maybe String)
?
更一般地说,什么函数具有类型 m1 m2 a - > (a - > m1 m2 b) - > m1 m2 b
?
额外问题:我将如何使用 IO中的符号$我已经定义了一个函数
useToken
context
$ b $ pre $
类型Token = String
getToken :: IO(也许令牌)
getToken = undefined
getUsername :: Token - > IO(可能是字符串)
getUsername = undefined
useToken :: IO(可能是String)
useToken = do
令牌< - getToken
case token
只需x - > getUsername x
Nothing - > return Nothing
如果您不想使用 do $ c
pre $ use $ or $ useToken2 :: IO(可能是字符串)
useToken2 = getToken> ;> = \ token - >也许(没有返回)getUsername令牌
或者使用monad变换器,你的代码将变得更简单:
import Control.Monad.Trans.Maybe
类型Token = String
getToken :: MaybeT IO令牌
getToken =未定义
getUsername ::令牌 - > MaybeT IO字符串
getUsername =未定义
useToken :: MaybeT IO字符串
useToken = do
令牌< - getToken
getUsername令牌
请注意,您也可以直接提升monad变换器中的IO操作。正如@Robedino所指出的那样,现在代码将更加简洁,不需要记号:
useToken :: MaybeT IO字符串
useToken = getToken>> = getUsername
I have two functions, one that tries to get a token from a webservice and may fail, and one that tries to use this token to get the username and may fail.
getToken :: IO (Maybe Token)
getUsername :: Token -> IO (Maybe String)
I would like to take the result of getToken and feed it to getUsername
. If there was only IO
or Maybe
, I could simply use bind, but since there are down nested monads, I can't. How can I write something equivalent to getToken >>= getUsername :: IO (Maybe String)
?
More generally, what function has type m1 m2 a -> (a -> m1 m2 b) -> m1 m2 b
?
Bonus question: how would I do that using the do notation in an IO
context?
I have defined a function useToken
showing your use case:
type Token = String
getToken :: IO (Maybe Token)
getToken = undefined
getUsername :: Token -> IO (Maybe String)
getUsername = undefined
useToken :: IO (Maybe String)
useToken = do
token <- getToken
case token of
Just x -> getUsername x
Nothing -> return Nothing
If you don't want to use do
notation, then you can use:
useToken2 :: IO (Maybe String)
useToken2 = getToken >>= \token -> maybe (return Nothing) getUsername token
Or using monad transformers, your code will become simpler:
import Control.Monad.Trans.Maybe
type Token = String
getToken :: MaybeT IO Token
getToken = undefined
getUsername :: Token -> MaybeT IO String
getUsername = undefined
useToken :: MaybeT IO String
useToken = do
token <- getToken
getUsername token
Note that, you can also directly lift IO operations inside the monad transformer. As @Robedino points out, now the code will be more concise without do notation:
useToken :: MaybeT IO String
useToken = getToken >>= getUsername
这篇关于如何使用bind与嵌套monads?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!