如何使用bind与嵌套monads? [英] How to use bind with nested monads?

查看:105
本文介绍了如何使用bind与嵌套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
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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆