2012-06-19 8 views
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")] 

このコードは非常に不可欠であると思われます。何とか簡単にすることはできますか?

答えて

9

は、Applicativeは、コンテキストに応じて、ここでの素敵なだけでなく、MaybeTである可能性があります。あなたが念頭に置くかもしれない3つ目は、doブロックバインディングのパターンマッチ失敗がfailを呼び出すということです。

これは私がどうなるのかです:MaybeT

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

または溶液を、異なる戻り値(再び多くのコンテキストが、これは良い方法かでないと表示される場合があります)との1はいえ:

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

は...実際には上記の今、私はあなたの第二重なりあっ再それで

+1

私はあなたの最初のアプローチが多くの最もクリーンであると思う。それは私がやっていることです、とにかく:)。 –

+2

+1必要なロジックのタイプを見たとき、私は直ちに「もしかして」と思った。あなたの 'fromMaybe'ソリューションはとてもきれいです。 MaybeTソリューションは悪くありません。 MaybeTを使用するコードのリファクタリングは、OPのケースでは良い選択かもしれません。 –

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前isJustチェックを取得する場合fromJustはほぼ常に悪いスタイルと少し危険であるコード。

これは、上記のように、

  • パターンマッチングにより向上させることがことができます。しかし、これがネストされていれば、それは醜くなります。
  • fromMaybeのようなコンビネータは、より簡潔にすることができます。
  • Maybe(およびMaybeT)をApplicativeまたはMonadとして使用すると、醜いネスティングを避けることができます。
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")] 

どのように迷惑です。

+0

を見てということではなく陳腐ですmpt: 'x :: Maybe(ByteString、ByteString)'ではなく 'x ::(Maybe ByteString、Maybe ByteString)'と思います。ファンクタ「<$>」と「<*>」は、「多分」ではなく「IO」で動作しています。 – dave4420

+0

'liftM2(、)<$> getPostParam"ログイン "<*> getPostParam"パスワード ">> = \ res - > case res of ...' – applicative

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 
+1

私はそれが 'render 'を定義しない方がきれいだと思います。 'と' authAs''を使用し、 'lift'をインラインで書くだけです。なぜなら、そのような関数は通常、何度も使用されないからです。 –

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

ああ、 'jberryman'による' fromMaybe'について忘れてしまった。私が '多分'それはちょうど 'fromMaybeメッセージ(liftM2 authAs ...)'であるべきである ' – applicative

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  
関連する問題