2012-02-18 15 views
1

m2とmが等しい場合、何も返さず地図を更新するIO操作(ネットワーク経由でいくつかのものを送り出す)を行いたいと思います。私は以下のコードを作って、これが何か不潔なものにリファクタリングできるかどうか(1)メッセージを送信すべきケース表現が評価されないか、少なくともメッセージが送信されないのはなぜですか?caseステートメントが評価されない

コードの下にコメントを付けると、私が望むように送信されますが、m2の値が何であるかを無視して送信されます。

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 

私は_平方メートルとmが等しくないすべてのケースのために定義されていないことを知っているが、SENDQ IO()返し、私は同じ型を返します| otherwise ->のためにここに追加する賢明な何かを考えることができませんでした。

答えて

4

_ = case m2 ofで始まる2行のコードは、まったく何もしません!これは、束縛値_が他の場所では使用されていない(または言及されていない)ため、決して評価されないためです。

あなたが探しているのは、おそらく、関数whenからControl.Monadまでです。タイプはMonad m => Bool -> m() -> m()です。次のようにあなたはそれを使用することができます。

when (m == m2) (send the messages ...) 

をしかし、あなたはすなわち、メインdo式の一部として、letブロックの外にそれを使用する必要があります。

もう一つは、あなたのコード:

 (q4, m4) = case m2 of 
       val | m2 == m -> deleteRec key q m2 
        | otherwise -> (q, m2) 

は次のように単純化することができます。

 (q4, m4) = if (m2 == m) then deleteRec key q m2 else (q, m2) 
+0

おかげで、私のために動作します。この場合、 '(m == m2)(fun1)'のとき、fun1の戻り値はどうなりますか?それは常に無視されますか? –

+0

@JFritschの場合、 'when'が動作するためには戻り値は'() 'でなければなりません。しかし、それは無視されると言えるでしょう。 – dflemstr

+0

@JFritsch:はい、そうです!あなたがそのタイプについてちょっと考えているならば、それが実際に行うことができる唯一の賢明なことでもあります。 'when'は'条件アクション=条件であればelse else return() 'のように定義され、' return() 'の部分には他にはあまりないものがあります。 'fun1'の結果に何が起こるのかをもっとコントロールしたいのであれば、あなた自身の' if ... then ... else ... 'ステートメントを書くことを検討すべきです。 – yatima2975

関連する問題