9

我有以下代码,我认为它很难看:

loginCheck = do
  ml <- getPostParam "login" -- ml and mp :: Maybe ByteString
  mp <- getPostParam "password"
  if isJust ml && isJust mp
    then authAs (fromJust ml) (fromJust mp)
    else render "Msg" [("text", "Form incomplete")]

这段代码似乎非常必要。我可以以某种方式简化它吗?

4

6 回答 6

12

怎么样:

loginCheck = do
  ml <- getPostParam "login" -- ml and mp :: Maybe ByteString
  mp <- getPostParam "password"
  case (ml,mp) of
    (Just l, Just p) -> authAs l p
    _ -> render "Msg" [("text", "Form incomplete")]

使用 isJust 和/或 fromJust 的代码几乎总是不好的风格,如果你在 fromJust 错误之前得到 isJust 检查,则有点危险。

这可以通过以下方式改进

  • 模式匹配,如上。但如果这是嵌套的,它会变得很难看。
  • 组合器,例如 fromMaybe 可以更简洁。
  • 使用 Maybe(和 MaybeT)作为 Applicative 或 Monad 可以避免丑陋的嵌套。
于 2012-06-19T20:53:38.340 回答
9

正如其他人所建议的那样,Applicative这里可能会很好,并且MaybeT取决于上下文。您可能要记住的第三件事是do块绑定调用中的模式匹配失败fail

这就是我要做的:

loginCheck = do
  ml <- getPostParam "login" 
  mp <- getPostParam "password"
  fromMaybe (render "Msg" [("text", "Form incomplete")]) $
            authAs <$> ml <*> mp

或者带有 的解决方案MaybeT,尽管返回值不同(更多的上下文可能再次表明这是一个好方法或不是):

getPostParamT = MaybeT . getPostParam
loginCheckT = do
    ml <- getPostParamT "login" -- ml and mp :: Maybe ByteString
    mp <- getPostParamT "password"
    liftIO $ authAs ml mp
   <|> (liftIO $ render "Msg" [("text", "Form incomplete")] )

...实际上,现在我看上面的内容是相当的

于 2012-06-20T00:15:38.593 回答
4
loginCheck = case (,) <$> getPostParam "login" <*> getPostParam "password" of
  Just (l, p)  -> authAs l p
  Nothing      -> render "Msg" [("text", "Form incomplete")]

也许?不,哎呀。

loginCheck = do
  x <- (,) <$> getPostParam "login" <*> getPostParam "password" of
  case x of
    Just (l, p)  -> authAs l p
    Nothing      -> render "Msg" [("text", "Form incomplete")]

多么烦人。

于 2012-06-19T20:54:12.510 回答
2

不确定这是否是一种改进,但也许在某些情况下......

import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe

getPostParam' = MaybeT . getPostParam
render' x y = lift (render x y)
authAs' x y = lift (authAs x y)

loginCheck = runMaybeT $ 
        go `mplus` render' "Msg" [("text", "Form incomplete")]
    where
        go = do
            ml <- getPostParam' "login"
            mp <- getPostParam' "password"
            authAs' ml mp
于 2012-06-19T22:54:23.277 回答
2
loginCheck = do
  [ml,mp] <- mapM getPostParam ["login","password"]
  case liftM2 authAs ml mp of 
    Nothing         -> render "Msg" [("text", "Form incomplete")]
    Just authorize  -> authorize

这可能看起来很奇怪,因为它在 a 上进行模式匹配Maybe (IO ()),但这是完全合理的。或者,使用maybe

loginCheque = mapM getPostParam ["login","password"] >>= \[ml,mp] -> 
              maybe message id (liftM2 authAs ml mp)
    where message = render "Msg" [("text", "Form incomplete")]
于 2012-06-19T22:55:58.957 回答
1
loginCheck = do 
  res <- return$ getPostParam "login" >>= \l -> -- ml and mp :: Maybe ByteString
                  getPostParam "password" >>= \p->
                   Just (l,p)
  case res of Nothing -> render "Msg" [("text", "Form incomplete")]
              (Just (l,p)) -> authAs l p       
于 2012-06-21T00:31:37.490 回答