ローマ数字を求める

1..3999の数字をローマ数字に変換する。
あとでググってみたら、ワンライナーとかすごそうなのが色々あったけど、自分としては今の実装で充分読みやすいと思った。Maybeを使って範囲外はNothingにしたりしてみたけど、このあたり空気は読めてない。
パターンマッチングは粗々こんな感じだろうけど、むしろモナドがでてくるここからがヤマなのだろう。
8/14追記:最初roman n の n mod 10|100|1000が0になるケースのパターンを網羅してなかった。実はそのことは知ってたんだけど、問題ないと思ってたら、roman 1900とかでエラーになったのでrecurなる関数を導入してきちんと漏れのないようにした。
パターンに漏れは禁物なんだな。

module Roman
where

roman' n one five ten | n == 0 = []
                      | n == 4 = [one, five]
                      | n == 5 = [five]
                      | n == 9 = [one, ten]
                      | n  > 5 = five : ( roman' (n-5) one five ten )
                      | otherwise = (roman' (n-1) one five ten) ++ [one]

roman n |    1 <= n && n <   10 =  roman'           n  'I' 'V' 'X'
        |   10 <= n && n <  100 =  roman' (div n   10) 'X' 'L' 'C' ++  recur (mod n   10)
        |  100 <= n && n < 1000 =  roman' (div n  100) 'C' 'D' 'M' ++  recur (mod n  100)
        | 1000 <= n && n < 4000 =  roman' (div n 1000) 'M' '-' '-' ++  recur (mod n 1000)
		where
		  recur n | n == 0 = []
		          | otherwise = roman n

chkroman n | n < 1     = Nothing
           | n < 4000  = Just $ roman n
           | otherwise = Nothing