ICPC: Problem A Keitai Message

Problem A: Keitai Messageより。Stateモナドを使って、こんな感じかな。今ひとつ美しさにかける気がします。

module Main (main) where

import Control.Monad.State (State, execState, get, put)
import Data.List (group, (!!))

key :: (Char, Int) -> State (Char, String) ()
key (c, n) = do
  (p, s) <- get
  case c of
    '1' -> put (k ".,!? ", s)
    '2' -> put (k "abc",   s)
    '3' -> put (k "def",   s)
    '4' -> put (k "ghi",   s)
    '5' -> put (k "jkl",   s)
    '6' -> put (k "mno",   s)
    '7' -> put (k "pqrs",  s)
    '8' -> put (k "tuv",   s)
    '9' -> put (k "wxyz",  s)
    '0' -> if (p /= '-') 
             then put ('-', p : s)
             else put ('-', s)
  where
    k t = cycle t !! (n - 1)

main :: IO ()
main = interact (unlines . map f . lines)
  where
    f l = reverse $ snd $ flip execState ('-', "") $ 
            mapM_ key [(head s, length s) | s <- group l]

入力:

5
20
220
222220
44033055505550666011011111090666077705550301110
000555555550000330000444000080000200004440000

出力:

a
b
b
hello, world!
keitai