Here is my solution for an exercise, which requires translation of strings to key presses on a phone keypad (for example, to get 'b' the digit '2' needs to be pressed twice).
It's taken from the book Haskell from first principles, and originally appeared in 1HaskellADay. I'd love to get feedback.
module Phone where
import Data.Char
import Data.String.Utils
import Data.List
data DaPhone = DaPhone [String]
convo :: [String]
convo =
["Wanna play 20 questions",
"Ya",
"U 1st haha",
"Lol ok. Have u ever tasted alcohol lol",
"Lol ya",
"Wow ur cool haha. Ur turn",
"Ok. Do u think I am pretty Lol",
"Lol ya",
"Haha thanks just making sure rofl ur turn"]
-- validButtons = "1234567890*#"
type Digit = Char
-- Valid presses: 1 and up
type Presses = Int
reverseTaps :: DaPhone -> Char -> [(Digit, Presses)]
reverseTaps (DaPhone keys) c = if isUpper c then ('*', 1) : looks else looks
where looks = look keys (toLower c)
-- assuming the default phone definition
-- 'a' -> [('2', 1)]
-- 'A' -> [('*', 1), ('2', 1)]
look :: [String] -> Char -> [(Digit, Presses)]
look keys c = look' keys c 0
look' :: [String] -> Char -> Int -> [(Digit, Presses)]
look' [] _ _ = []
look' (x:xs) c n = if ind /= (-1) then [(head $ show n, ind + 1)] else look' xs c (n + 1)
where ind = maybe (-1) id $ elemIndex c x
cellPhonesDead :: DaPhone -> String -> [(Digit, Presses)]
cellPhonesDead = (concat .) . map . reverseTaps
-- count total presses
fingerTaps :: [(Digit, Presses)] -> Presses
fingerTaps = sum . map snd
mostPopularLetter :: String -> Char
mostPopularLetter = head . longest . group . sort
coolestLtr :: [String] -> Char
coolestLtr = mostPopularLetter . filter isAlpha . concat
coolestWord :: [String] -> String
coolestWord = head . longest . group . sort . words . join " "
longest :: [[a]] -> [a]
longest = maximumBy (\x y -> compare (length x) (length y))
phone :: DaPhone
phone = DaPhone keymap
keymap :: [String]
keymap =
[
" 0",
"1",
"abc2",
"def3",
"ghi4",
"jkl5",
"mno6",
"pqrs7",
"tuv8",
"wxyz9"
]