Today’s Programming Praxis problem is about morse code. We’re supposed to write a program to convert back and forth between plain text and morse code. Shouldn’t be too hard, so let’s go.
First our imports:
import Data.List import Data.List.Split import qualified Data.Map as M
Next we need to define the morse code. Unlike the solution posted by the Programming Praxis author, however, we’re not going to specify the translations both ways, as that would go against the DRY (Don’t Repeat Yourself) principle (or Once And Only Once, whichever you prefer). So instead we just make two lists of the valid characters, making sure to match the order.
plain :: [Char] plain = ['A'..'Z'] ++ ['0'..'9'] morse :: [String] morse = words ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- \ \-. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.. \ \.---- ..--- ...-- ....- ..... -.... --... ---.. ----. -----"
Converting a character to a morse symbol or vice versa is then simply a matter of:
convert :: Ord a => [a] -> [b] -> a -> b convert from to x = M.fromList (zip from to) M.! x
The functions to convert between whole strings also involve some mucking about with the spaces.
toMorse :: String -> String toMorse = intercalate " " . map (unwords . map (convert plain morse . toUpper)) . words fromMorse :: String -> String fromMorse = unwords . map (map (convert morse plain) . words) . splitOn " "
And that’s all you need. To test you just use something like:
main :: IO () main = do print $ toMorse "Programming Praxis" print $ fromMorse ".--. .-. --- --. .-. .- -- -- .. -. --. \ \.--. .-. .- -..- .. ..."
And there we go. Three (nearly) one-liners and some data. Piece of cake