Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read an Int in one line of code?

Tags:

haskell

I'm just starting to learn Haskell after first getting my hands dirty in functional programming with python.

First of all, I know what I will ask is bad practice is virtually every programming language known to man, and I promise to not use this in any serious purpose other than purely educational. That said...

One of the things I liked best was the elegance of writing a function using just one line of code while still keeping the code readable(things like C/C++ style where you just place all the statements on one line separated by semicolons don't count, obviously)

I have looked trough questions and tried at least a few different haskell tutorials and documentations and some things have gotten close, but I could not find something that lets me read a usable Int in one line of code.

For the sake of the question let's say I want something like reading an Int for the keyboard and printing "Hello World!" that many times(shamelessly stolen from HackerRank).

The things I have tried using getLine, readLn, read, looked into >>= instead of do notation, only to remain stuck with IO operations stubbornly giving me an error every time I did not put them in a separate statement.

Some of the things I have tried:

main :: IO ()
main = readLn :: IO Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!"

gives:

parse error on input ‘\’

Then

main = readLn >>= \n -> read n :: Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!"

Gives the same error.

Same with:

main = getLine >>= \n -> read n :: Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!"

What exactly am I not understanding? Thanks in advance!

like image 330
Rares Dima Avatar asked Oct 18 '25 09:10

Rares Dima


1 Answers

You're mixing type declarations with expressions. It should be:

main = (readLn :: IO Int) >>= \n -> mapM_ putStrLn $ replicate n "Hello World!"

Your problem was that without bracketing, the compiler continues to parse as if it were reading a type declaration, and so it ran across \ and got stuck.

However, this type declaration is inferred (since replicate :: Int -> a -> [a]) and thus unnecessary. Remove it!

main = readLn >>= \n -> mapM_ putStrLn $ replicate n "Hello World!"

In general however, it's much better to avoid this entirely and just use do-notation. This kind of 'golfing' in Haskell is very fun, but not the way to make clear, maintainable code.

import Control.Monad (replicateM_)

main = do
    n <- readLn :: IO Int                   -- Type optional here.
    replicateM_ n $ putStrLn "Hello World!" -- A more concise expression.
like image 125
AJF Avatar answered Oct 22 '25 03:10

AJF