Print a sequence of n numbers
You can use unwords in place of intercalate " ".

Given the type signature of getInteger :: String -&gt; Integer the return type of read xs must be Integer in order for the type system to unify what you've written, making your type annotation on the function implementation there redundant. You can perform eta-reduction on getInteger then (that is, write it in pointfree style) and drop the xs for an implementation of&mdash;

getInteger :: String -&gt; Integer
getInteger = read


This is now obviously a specialization of read, which isn't all that interesting. Look now to the implementation of nthLineStr where you can see that the result of getInteger xs is passed to nthLine. Because the type of nthLine is given as Integer -&gt; String, the compiler can again determine that read must return an Integer if you change the definition of nthLineStr to&mdash;

nthLineStr :: String -&gt; String
nthLineStr xs = nthLine (read xs)


You can perform eta-reduction again to write nthLineStr as nthLineStr = nthLine . read. nthLineStr is a bit of a kludge though, in that it muddies the waters between your pure code and the outside world. Keep your (de-)serialization functions apart from the rest of your program, it shouldn't matter to the core logic of your application whether you were passed a String or a Text value or length encoded sequence of unit values ([()]).

main :: IO ()
main = do n &lt;- fmap read getLine
       putStrLn $ nthLine n


Or you could use another Prelude function, interact :: (String -&gt; String) -&gt; IO () (a useful concept, but note this changes the semantics a bit).

main :: IO ()
main = interact (nthLine . read)