简化可能的表达式

时间:2012-06-19 20:50:54

标签: haskell

我有以下代码,我觉得它很难看:

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")]

这段代码似乎非常迫切。我能以某种方式简化它吗?

6 个答案:

答案 0 :(得分: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检查,那就有点危险了。

这可以通过

来改进
  • 模式匹配,如上所述。但如果这是嵌套的,那就太难看了。
  • 组合者,比如来自Maybe可以更简洁。
  • 使用Maybe(和MaybeT)作为Applicative或Monad可以避免丑陋的嵌套。

答案 1 :(得分: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")] )

......实际上上面的内容现在让我看起来很好看

答案 2 :(得分: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")]

多么烦人。

答案 3 :(得分: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

答案 4 :(得分:2)

loginCheck = do
  [ml,mp] <- mapM getPostParam ["login","password"]
  case liftM2 authAs ml mp of 
    Nothing         -> render "Msg" [("text", "Form incomplete")]
    Just authorize  -> authorize

这可能看起来很奇怪,因为它在Maybe (IO ())上匹配模式,但这听起来很完美。或者,使用maybe

loginCheque = mapM getPostParam ["login","password"] >>= \[ml,mp] -> 
              maybe message id (liftM2 authAs ml mp)
    where message = render "Msg" [("text", "Form incomplete")]

答案 5 :(得分: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