Reputation: 3358
If m2 and m are equal I want to do an IO operation (send out some stuff over the network) that returns nothing and update my map. I have crafted the following code and wonder (1) if this can be refactored into something less clunky (2) why my case expression that should send out the messages does not get evaluated or at least no messages do get send.
If I uncomment the code at the bottom then things do get send as I want to, but of course it is then send out disregarding what the value of m2 is.
main = withSocketsDo $ do
s <- socket AF_INET Datagram defaultProtocol
(q, m) <- newRq
let m2 = appendMsg "first" key m
_ = case m2 of
val | m2 == m -> do let Just messages = Map.lookup ("192.168.1.1", 4711) m in sendq s (B.pack $ unwords messages) "192.168.1.1" 4711
(q4, m4) = case m2 of
val | m2 == m -> deleteRec key q m2
| otherwise -> (q, m2)
--let Just messages = Map.lookup ("192.168.1.1", 4711) m
--sendq s (B.pack $ unwords messages) "192.168.1.1" 4711
I know that _ is not defined for all cases where m2 and m are not equal, but sendq returns IO ()
and I could not think of something sensible to add here for | otherwise ->
that would return the same type.
Upvotes: 1
Views: 158
Reputation: 6610
The two lines of code starting with _ = case m2 of
do exactly nothing! This is because the bound value _
never gets evaluated, because it is not used (or even mentioned) anywhere else.
What you are looking for is, I guess, the function when
from Control.Monad
. It has type Monad m => Bool -> m () -> m()
; you could use it as follows:
when (m == m2) (send the messages ...)
but you would have to use it outside the let
block, i.e. as part of the main do
expression.
One more thing, your code:
(q4, m4) = case m2 of
val | m2 == m -> deleteRec key q m2
| otherwise -> (q, m2)
can be simplified to:
(q4, m4) = if (m2 == m) then deleteRec key q m2 else (q, m2)
Upvotes: 4