2

このコードでは:

 fromMaybe <$> (print "A" >> return True) <*> (print "B" >> (return $ Just False))
 fromMaybe <$> (print "A" >> return True) <*> (print "B" >> (return $ Nothing))

怠惰のために、私が提供するかどうかに応じて「A」または「B」のいずれかが印刷されるか、代わりに両方が印刷されると予想しましJust somethingNothing。誰かが a) 正確にここで何が起こっているのか説明できますか? b) 希望する効果を得るにはどうすればよいですか?

4

2 に答える 2

3

次のことが起こります。

fromMaybe を IO 値にマップします。したがって、左側の部分

fromMaybe <$> (print "A" >> return True) 

このように書き換えることができる IO アクションです。

print "A" >> return (fromMaybe True) :: IO (Maybe Bool -> Bool)

これは、「A」が何があっても印刷されることを意味します。

IO モナドはすべてアクションの順序付けに関するものであることに注意してください。したがって、 >>= チェーンの後のアクションは、以前のアクションが実行されるかどうかに影響を与えることはできません。

検討

fromMaybe <$> (getChar >>= return) 

fromMaybe が適用される Char は、実際に文字を読み取った結果である必要があることは明らかです。文字が必要なときにだけ読み取られるというわけではありません。

その場合、次のコードは意味をなしません。

do
    a <- getChar
    b <- getChar
    -- at this point, a and b have been actually read from stdin already
    return (a < b)

(<) がその左または右の引数を最初に評価するかどうかは不明です。

いずれにせよ、a は最初に読み取った文字の値を取得し、b は 2 番目の文字の値を取得します。したがって、コード スニペットの意味は、2 つの文字を読み取り、読み取った最初の文字が 2 番目の文字よりも小さいかどうかを確認することです。

実際、その値が実際に必要な場合にのみ IO アクションが実行される場合、多くのプログラムはそのままでは何も出力しません。これは、次のようなコードのためです。

 print "A" >> print "B"

最初の印刷の結果を意図的に無視します。

同じ理由で、「B」は常に印刷されます。

于 2013-07-09T19:00:21.470 に答える