"Hell Difficulty" Haskell Fast & Hard I'm a complete neophyte to Haskell with only a smidge of FP experience – I did some Racket programming academically and have written some semi-FP JavaScript professionally, but now I'm trying to learn Haskell (and FP better). So I read Haskell Fast &amp; Hard with no problems up until the last chapter.

Monads.


  Make a program that sums all of its arguments. Hint: use the function getArgs.


I eventually wrote a program that nominally achieves this requirement, but it felt very hacky. For reference, here is a "correct" program by the author that I think I was supposed to model after. It sums the numbers in a comma-delimited string.

import Data.Maybe

maybeRead :: Read a =&gt; String -&gt; Maybe a
maybeRead s = case reads s of
                  [(x,"")]    -&gt; Just x
                  _           -&gt; Nothing
getListFromString :: String -&gt; Maybe [Integer]
getListFromString str = maybeRead $ "[" ++ str ++ "]"
askUser :: IO [Integer]
askUser = do
  putStrLn "Enter a list of numbers (separated by comma):"
  input &lt;- getLine
  let maybeList = getListFromString input in
      case maybeList of
          Just l  -&gt; return l
          Nothing -&gt; askUser
-- show
main :: IO ()
main = do
  list &lt;- askUser
  print $ sum list


Based on the above approach, I wrote a function to convert the list of argument-strings back into a comma-delimited string so that most of the other functions could work unchanged.

import Data.Maybe
import System.Environment (getArgs)

maybeRead :: Read a =&gt; String -&gt; Maybe a
maybeRead s = case reads s of
                  [(x,"")]    -&gt; Just x
                  _           -&gt; Nothing
getListFromString :: String -&gt; Maybe [Integer]
getListFromString str = maybeRead $ "[" ++ str ++ "]"
getArgsAsString :: [String] -&gt; String
getArgsAsString [] = "0"
getArgsAsString (x:xs) = x ++ "," ++ getArgsAsString xs
askUser :: [String] -&gt; [Integer]
askUser input = case (getListFromString (getArgsAsString input)) of
            Just l  -&gt; l
            Nothing -&gt; error "failsauce"
main :: IO ()
main = do
  input &lt;- getArgs
  print $ sum (askUser input)


I am trying to stick to the spirit of the exercise and not go too far into library functions that solve the problem for me without teaching me anything (in particular, the author says not to try too hard to understand the syntax of maybeRead), but it feels very wrong to convert a list of strings to a comma-separated string only to split it out again into a maybe-list of integers.

All advice is appreciated! (But educational guidance is appreciated more than "just use xyz lib function".)
There's very little I would salvage from the model code.


Converting the arguments list into comma-separated string is a little hackish and not very efficient (nevertheless it works, and I'd be totally OK with it for a quick throw away script). Therefore I would not use getListFromString.
askUser is not needed since we're not interacting with the user.
There's already an alternative to maybeRead, in Text.Read called readMaybe.


This is how I would implement it:

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

main :: IO ()
main = do
  values &lt;- fmap (map readMaybe) getArgs
  putStrLn $ maybe "Arguments invalid" (show . sum) $ sequence values