I have the following code, and I think it is ugly:
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")]
This code seems to be very imperative. Can I simplify it somehow?
For example, 1/2 (x + 4) can be simplified as x/2 + 2. Let us take one more example to understand it. Example: Simplify the expression: 3/4x + y/2 (4x + 7). By using the distributive property, the given expression can be written as 3/4x + y/2 (4x) + y/2 (7).
In general, an expression is in simplest form when it is easiest to use. Example, this: 5x + x − 3.
How about:
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")]
Code that uses isJust and/or fromJust is nearly always bad style and slightly dangerous if you get the isJust check before fromJust wrong.
This can be be improved by
As others have suggested, Applicative
could be nice here, as well as MaybeT
depending on the context. A third thing you might keep in mind is that a pattern match failure in a do
block binding calls fail
.
This is what I would do:
loginCheck = do
ml <- getPostParam "login"
mp <- getPostParam "password"
fromMaybe (render "Msg" [("text", "Form incomplete")]) $
authAs <$> ml <*> mp
Or a solution with MaybeT
, albeit one with a different return value (again more context might show this to be a good approach or not):
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")] )
...actually the above is rather hokey now that I look at it
loginCheck = case (,) <$> getPostParam "login" <*> getPostParam "password" of
Just (l, p) -> authAs l p
Nothing -> render "Msg" [("text", "Form incomplete")]
perhaps? No. Oops.
loginCheck = do
x <- (,) <$> getPostParam "login" <*> getPostParam "password" of
case x of
Just (l, p) -> authAs l p
Nothing -> render "Msg" [("text", "Form incomplete")]
How annoying.
Not sure if this is an improvement here, but maybe in some cases...
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
loginCheck = do
[ml,mp] <- mapM getPostParam ["login","password"]
case liftM2 authAs ml mp of
Nothing -> render "Msg" [("text", "Form incomplete")]
Just authorize -> authorize
This might seem strange because it pattern matches on a Maybe (IO ())
, but this is perfectly sound. Or, using maybe
:
loginCheque = mapM getPostParam ["login","password"] >>= \[ml,mp] ->
maybe message id (liftM2 authAs ml mp)
where message = render "Msg" [("text", "Form incomplete")]
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With