まず、IO のことは忘れてください。
labelInteger :: String -> Integer -> String
labelInteger label number = label ++ ": " ++ show number
ここで、IO について心配します。
import Control.Monad (liftM, liftM2)
labelIOInteger :: String -> IO Integer -> IO String
labelIOInteger label ioNumber = liftM (labelInteger label) ioNumber
例として使用しlabelIOInteger "Screen Width" getScreenWidthます...しかし注意してください!次のようなことをすると:
widthLabel <- labelIOInteger "Screen width" getScreenWidth
isPortrait <- liftM2 (<) getScreenWidth getScreenHeight
...その後getScreenWidth2 回実行されます...確かに、この特定のアクションでは問題になりそうにありませんが、ファイル、データベース、または Web サイトから整数を読み取るアクションである場合は、それを実行することがわかります。 2 回は望ましくない場合があります。
通常は、 のような関数を記述しない方がよいでしょうlabelIOInteger。代わりに、次のようにします。
widthLabel <- liftM (labelInteger "Screen Width") getScreenWidth
...そのため、2 つの異なる計算に戻り値を使用する必要がある場合は、次のように簡単にリファクタリングできます。
screenWidth <- getScreenWidth
let widthLabel = labelInteger "Screen Width" screenWidth
isPortrait <- liftM (screenWidth <) getScreenHeight