简化可能的表达式

dem*_*emi 9 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")]
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*icz 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")]
Run Code Online (Sandbox Code Playgroud)

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

这可以通过改进

  • 模式匹配,如上所述.但如果这是嵌套它会变得丑陋.
  • 组合者,比如来自Maybe,可以更简洁.
  • 使用Maybe(和MaybeT)作为Applicative或Monad可以避免丑陋的嵌套.


jbe*_*man 9

正如其他人所建议的那样,Applicative在这里可能会很好,也可能MaybeT取决于具体情况.您可能要记住的第三件事是do块绑定调用中的模式匹配失败fail.

这就是我要做的:

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

或者是一个解决方案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")] )
Run Code Online (Sandbox Code Playgroud)

......实际上,现在看起来我已经很开心了

  • 当我看到所需的逻辑类型时,我立刻想到了`fromMaybe` + applicatives.你的`fromMaybe`解决方案很干净.MaybeT解决方案并不错; 重构大量代码以使用MaybeT可能是OP的一个很好的选择. (2认同)