nobsun さんよりグローバル変数というトラックバックを頂いたので、お答えします。
直前にあるコード例では、「処理結果(cflag など)を下位の関数にずっと渡していかないといけない」部分が省略されているようでよくわからない。
たとえば、UNIX の od コマンドでは、-c オプションで ASCII 表記になります。それをunsafePerformIO なしで実装すると、僕だと以下のように書いてしまいます。
main = do argv <- getArgs let cflag = "-c" `elem` argv putStr $ func1 cflag func1 cflag = func2 cflag func2 cflag = func3 cflag func3 cflag = func4 cflag func4 cflag = if cflag then "ASCII string" else "HEX string"
別の方法としては、func4 内で getArgs を使い、func4 の型を IO String にすることですが、すると func1 〜 func3 までが全部 IO に侵されてしまいます。
僕の頭が C に毒されているだけで、もっとちゃんとした方法があるのかもしれませんね。