なぜ Haskell の (IO a) は IO でパターンマッチできないのか
なんてことを思ったわけです。
ちょっと考えるとただの勘違いなので恥ずかしいです。
まず IO a はそういう型名なのであって IO a という型コンストラクタではないということです。
IO の型定義は http://www.haskell.org/ghc/docs/latest/html/libraries/ghc-prim-0.2.0.0/src/GHC-Types.html#IO に書いてありますが、ここを見るとわかるように
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
となっている訳ですね。
これは State モナドの定義となっていて、誤解を恐れずに言うと
IO 操作というのは、世界を引数にとって IO 操作後の世界と何かの値を返す関数
となっているわけです。
なのでそもそも (IO a) という型は a という値そのものをバインドしているのではなく、
世界に干渉して a を持ってきてくれる関数な訳ですね。
なので IO は単純なパターンマッチでは剥がすことはできません。