import Data.Char (toUpper) import Data.Maybe (fromMaybe) import Text.Printf (PrintfType, printf) dirs :: [String] dirs = [ "N" , "NbE" , "N-NE" , "NEbN" , "NE" , "NEbE" , "E-NE" , "EbN" , "E" , "EbS" , "E-SE" , "SEbE" , "SE" , "SEbS" , "S-SE" , "SbE" , "S" , "SbW" , "S-SW" , "SWbS" , "SW" , "SWbW" , "W-SW" , "WbS" , "W" , "WbN" , "W-NW" , "NWbW" , "NW" , "NWbN" , "N-NW" , "NbW" ] -- Index between 0 and 31 -> the corresponding compass point name. pointName :: Int -> String pointName = capitalize . concatMap (fromMaybe "?" . fromChar) . (dirs !!) where fromChar c = lookup c [ ('N', "north") , ('S', "south") , ('E', "east") , ('W', "west") , ('b', " by ") , ('-', "-") ] capitalize (c:cs) = toUpper c : cs -- Degrees -> compass point index between 0 and 31. pointIndex :: Double -> Int pointIndex d = (round (d * 1000) + 5625) `mod` 360000 `div` 11250 printPointName :: PrintfType t => String -> t printPointName d = let deg = read d :: Double idx = pointIndex deg in printf "%2d %-18s %6.2f°\n" (idx + 1) (pointName idx) deg main :: IO () main = mapM_ (printPointName . show) [0 .. 31]