RosettaCodeData/Task/Morse-code/Haskell/morse-code-2.hs

37 lines
1.7 KiB
Haskell

module MorseCode (Morse, MSym(..), toMorse) where
import Data.List
import Data.Maybe
import qualified Data.Map as M
type Morse = [MSym]
data MSym = Dot | Dash | SGap | CGap | WGap deriving (Show)
-- Based on the table of International Morse Code letters and numerals at
-- http://en.wikipedia.org/wiki/Morse_code.
dict = M.fromList
[('a', m ".-" ), ('b', m "-..." ), ('c', m "-.-." ), ('d', m "-.." ),
('e', m "." ), ('f', m "..-." ), ('g', m "--." ), ('h', m "...." ),
('i', m ".." ), ('j', m ".---" ), ('k', m "-.-" ), ('l', m ".-.." ),
('m', m "--" ), ('n', m "-." ), ('o', m "---" ), ('p', m ".--." ),
('q', m "--.-" ), ('r', m ".-." ), ('s', m "..." ), ('t', m "-" ),
('u', m "..-" ), ('v', m "...-" ), ('w', m ".--" ), ('x', m "-..-" ),
('y', m "-.--" ), ('z', m "--.." ), ('1', m ".----"), ('2', m "..---"),
('3', m "...--"), ('4', m "....-"), ('5', m "....."), ('6', m "-...."),
('7', m "--..."), ('8', m "---.."), ('9', m "----."), ('0', m "-----")]
where m = intersperse SGap . map toSym
toSym '.' = Dot
toSym '-' = Dash
-- Convert a string to a stream of Morse symbols. We enhance the usual dots
-- and dashes with special "gap" symbols, which indicate the border between
-- symbols, characters and words. This allows a player to easily adjust its
-- timing by simply looking at the current symbol, rather than trying to keep
-- track of state.
toMorse :: String -> Morse
toMorse = fromWords . words . weed
where fromWords = intercalate [WGap] . map fromWord
fromWord = intercalate [CGap] . map fromChar
fromChar = fromJust . flip M.lookup dict
weed = filter (\c -> c == ' ' || M.member c dict)