2012-06-19 37 views
9

Tôi có đoạn code sau, và tôi nghĩ rằng đó là xấu xí:Đơn giản hóa biểu thức Có lẽ

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

Mã này có vẻ là rất cấp bách. Tôi có thể đơn giản hóa nó bằng cách nào đó?

Trả lời

9

Như những người khác đã gợi ý, Applicative có thể được tốt đẹp ở đây, cũng như MaybeT tùy thuộc vào ngữ cảnh. Điều thứ ba bạn có thể lưu ý là lỗi khớp mẫu trong một cuộc gọi ràng buộc chặn dofail.

Đây là những gì tôi sẽ làm:

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

Hoặc một giải pháp với MaybeT, mặc dù một với một giá trị trả về khác nhau (bối cảnh một lần nữa hơn có thể hiển thị này là một cách tiếp cận tốt hay không):

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

... thực sự ở trên là khá hokey bây giờ mà tôi nhìn vào nó

+1

Tôi nghĩ rằng cách tiếp cận đầu tiên của bạn là sạch nhất của lô. Đó là những gì tôi sẽ làm, dù sao đi nữa :). –

+2

+1 khi tôi nhìn thấy loại logic cần thiết, tôi ngay lập tức nghĩ rằng 'fromMaybe' + ứng dụng. Giải pháp 'fromMaybe' của bạn rất sạch sẽ. Giải pháp MightT không phải là xấu; refactoring swaths lớn hơn của mã để sử dụng MaybeT có thể là một lựa chọn tốt trong trường hợp của OP. –

12

Làm thế nào về:

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

Mã sử ​​dụng isJust và/hoặc fromJust là gần như luôn luôn phong cách xấu và hơi nguy hiểm nếu bạn nhận được séc isJust trước fromJust sai.

này có thể được cải thiện bằng

  • mẫu phù hợp, như ở trên. Nhưng nếu điều này được lồng vào nhau thì nó trở nên xấu xí.
  • Kết hợp, như từMaybe có thể gọn gàng hơn.
  • Sử dụng Có thể (và Có thể) khi Áp dụng hoặc Monad có thể tránh được việc làm xấu xí.
4
loginCheck = case (,) <$> getPostParam "login" <*> getPostParam "password" of 
    Just (l, p) -> authAs l p 
    Nothing  -> render "Msg" [("text", "Form incomplete")] 

có lẽ? Không.

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

Làm thế nào gây phiền nhiễu.

+0

Re Atte thứ hai của bạn mpt: Tôi nghĩ rằng 'x :: (Có lẽ ByteString, Có lẽ ByteString)', không 'x :: Có lẽ (ByteString, ByteString)'. Hàm functor '<$>' và '<*>' đang hoạt động trên là 'IO', không phải' Có thể'. – dave4420

+0

Ông chỉ cần thêm liftM2 trước khi trường hợp: 'liftM2 (,) <$> getPostParam" đăng nhập "<*> getPostParam" mật khẩu ">> = \ res -> trường hợp res của ...' – applicative

2

Không chắc nếu điều này là một sự cải tiến ở đây, nhưng có lẽ trong một số trường hợp ...

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

Tôi nghĩ rằng nó sạch hơn để không xác định 'render ' 'và' authAs'', và chỉ viết 'nội tuyến', bởi vì một hàm như vậy thường sẽ không được sử dụng nhiều hơn một lần. –

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

này có vẻ kỳ lạ bởi vì nó phù hợp với mô hình trên Maybe (IO()), nhưng điều này là hoàn toàn âm thanh. Hoặc, sử dụng maybe:

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

Ồ, quên đi 'fromMaybe' được đề cập bởi 'jberryman'; nơi tôi sử dụng 'có lẽ 'nó chỉ nên là' từ tin nhắnMaybe (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  
Các vấn đề liên quan