繁体   English   中英

Haskell与多个monad绑定

[英]Haskell bind with multiple monads

现在,我的代码如下所示:

postUser :: ServerPart Response
postUser = do
  -- parseBody :: ServerPart (Maybe User)
  parsedUser <- parseBody
  case parsedUser of
    Just user -> do
      -- saveUser :: User -> ServerPart (Maybe (Key User))
      savedUser <- saveUser user
      case savedUser of
        Just user -> successResponse
        Nothing   -> errorResponse "user already exists"
    Nothing   -> errorResponse "couldn't parse user"

哪个可行,但是我知道有一种避免嵌套模式匹配的方法。 我以为这就是bind对我的影响,所以我尝试了

parseUser :: ServerPart (Maybe User)
addUser :: User -> ServerPart (Maybe ())
case parseUser >>= saveUser of
  Just _  -> success
  Nothing -> error

savedUser <- (parseUser >>= saveUser)
case savedUser of
  Just _  -> success
  Nothing -> error

但是我收到以下错误:

Couldn't match type ‘Maybe a0’ with ‘User’
    Expected type: Maybe a0 -> ServerPartT IO (Maybe (Key User))
      Actual type: User -> ServerPart (Maybe (Key User))
    In the second argument of ‘(>>=)’, namely ‘saveUser’
    In the expression: parseBody >>= saveUser

我的意思是>>=正在将saveUser应用于Maybe User而不是我需要的User ,而且我不确定如何确定类型以匹配。 我该如何重写以避免嵌套模式匹配?

尽管我认为原始的编写方式是最易读的方法,但作为练习,MaybeT monad转换器正是您所需要的。

您遇到的问题是您正在尝试在ServerPart monad和Maybe monad之间跳转。 这就是为什么您不能直接绑定parseBody和saveUser的原因。 Monad变压器使您可以组合Monad来避免此问题。

import Control.Monad.Trans.Maybe

postUser :: ServerPart Response
postUser = do
  -- parseBody :: MaybeT ServerPart User
  -- saveUser :: User -> MaybeT ServerPart (Key User)
  user <- runMaybeT $ parseBody >>= saveUser
  case user of
    Just _ -> successResponse
    Nothing -> errorResponse "Error saving user"

您将需要重构parseBody和saveUser函数以使用MaybeT monad。 由于看不到这些功能,因此无法为您提供帮助,但是通常可以使用Control.Applicative中的lift轻松完成此操作。

monad变压器上的有用链接:

https://zh.wikibooks.org/wiki/Haskell/Monad_transformers https://www.schoolofhaskell.com/user/commercial/content/monad-transformers

编辑:也许是parseBody

parseBody :: FromJSON a => MaybeT ServerPart a
parseBody = MaybeT $ fmap A.decode getBody

就像一般提示: bar >>= (return . f) fmap f bar bar >>= (return . f)等效于fmap f bar 后者更干净,更通用,因为它不需要monad实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM