otherwise パターン(?)

FizzBuzz とか FibBuzz で,

let n = case args of
          []        -> 30
          [x]       -> read x
          otherwise -> error "Invalid Program Option"

って何気なく書いてたけど,これ,よく考えるとおかしいです.


僕としては,ガードを使って

let x = case n of
          n | n < 0     = "negative"
            | otherwise = "not negative"

って書いてるつもりで otherwise を使ってたのですが,
最初のコードだと, otherwise はガードじゃなくてパターン部分に書かれてるよね.
otherwise パターンなんて物は存在しない筈なのに,なんでこれ,コンパイル通るんでしょうか?


結論をいってしまうと,これは単に, otherwise という変数に値を束縛しているだけです.
具体的に例を挙げて説明すると,

let n = case args of
          []        -> 30
          [x]       -> read x
          otherwise -> error $ show otherwise

上の case 式における show otherwiseotherwise は,
Prelude.otherwise ではなく args の中身が束縛される変数なので,
args として(例えば) ["1", "2"] を渡すと,
show otherwise"True" ではなく "[\"1\",\"2\"]" になります.


もちろん,本来なら,これは

let n = case args of
          []  -> 30
          [x] -> read x
          _   -> error "Invalid Program Option"

と書くべきです.
コンパイルエラーにならず,(結果的には)意図した通りの動作になるとはいえ,
パターンマッチ内のガードで Prelude.otherwise を使おうとした場合には,事故る可能性があるので.


後で書き直す.