J Fritsch
J Fritsch

Reputation: 3358

case statement not evaluated

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

Answers (1)

yatima2975
yatima2975

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

Related Questions