3
\$\begingroup\$

The following code parses a 2D Cartesian coordinate passed as Cart2Pol <x> <y> and prints the coordinate in rho, theta (polar) form. The operation itself is trivial, however I am interested in critique on the "boiler plate" code to take the args, parse them, compute and print the result.

The Haskell source is as follows:

module Main where

import System.Environment (getArgs)
import Text.Read (readMaybe)

cart2pol :: Float -> Float -> (Float, Float)
cart2pol x y = (rho, theta)
  where
    rho = sqrt $ x**2 + y**2
    theta = atan2 y x

readFloat :: String -> Maybe Float
readFloat = readMaybe

convert :: Maybe Float -> Maybe Float -> (Float, Float)
convert (Just x) (Just y) = cart2pol x y
convert _ _ = error "x and y must be Float"

main :: IO ()
main = do
  args <- getArgs
  case args of
    [x, y] -> do
      let rt = convert (readFloat x) (readFloat y)
      putStrLn $ "rho: " ++ show (fst rt) ++ " theta: " ++ show (snd rt)
    _ -> putStrLn "Usage: CartToPol x y"

What are some ways I could make this code more succinct?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

For a complete executable that actually does anything, this is fine and to-the-point. Trying to reduce boiler-plate would just be golfing.

cart2pol is great. If this is part of a larger code-base, then introducing data types for coordinates would be good, but if this is the whole thing then don't bother.

So most of your complexity is just reading and handling the CLI arguments! Since the application is pretty simple and your needs are easy, I don't think you'll be able to write anything shorter, but you still might want to learn to use a library for this task. I've had good luck with optparse-applicative.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.