Extracting an integer command-line argument and printing a sum of numbers up to that limit The below code works fine but I have the feeling that there must be something more idiomatic way to do this within the do-notation without having to resort to the two liftMs?

main = do
  n &lt;- (liftM read (liftM head getArgs)) :: IO Int
  putStrLN . show $ sum [1..n]


If I do:


main = do
  args &lt;- getArgs
  arg1 &lt;- head args
  n &lt;- read arg1 :: IO Int
  putStrLn . show $ sum [1..n]



I get:

Expected type: String
  Actual type: Char
In the first Argument of 'read', namely 'arg1'


which I do not understand. &lt;- getArgs returns IO [String], so &lt;- head args should return IO String, but it seems to return IO Char?! (as per error message).

So my two questions are:


what is the most idiomatic way do do this
what's wrong in the second version?
This is the code you're looking for:

main = do
  args &lt;- getArgs
  let arg1 = head args
  let n = (read arg1) :: Int
  putStrLn . show $ sum [1..n]


Think of the &lt;- operator as "extract". It "pulls" a value out of a monad. 

But once you've pulled args out of the IO monad, you've now got a pure list of strings. It's not in the IO monad, so you can't extract from it. let instead just does a pure binding like you're used to in non-monadic code, which is what you need here.