How to read input from the user? - haskell

How to ask a user to give a number of 7 digits and define a
function which converts these digits into a list of individual Integers. The example:
toDigits (1234567) = [1, 2, 3, 4, 5, 6, 7]
toDigitsReverse 1234567 = [7, 6, 5, 4, 3, 2, 1]
NB. (1234567) should be entered by the user.
I know how to prompt the user and the function to get it into an array but I do not know how to put them together. This is what I get so far - the function to separate them.
toDigits :: Integral x => x -> [x]
toDigits 0 = []
toDigits x = toDigits (x div 10) ++ [x mod 10]
main :: IO ()
main = do
putStr "The split array is "
print(toDigits 1234567)
How to get the todigit function to accept input?
I also tried the following but it gives an error
toDigits :: Integer -> [Int]
toDigits n = map (\x -> read [x] :: Int) (show n)
main :: IO ()
main = do
putStrLn "Please enter the USI number: "
usi <- getLine
let usiasnumber = read usi :: Int
print("The USI split into single digit array is " ++ toDigits usiasnumber)
I did this but its not working. Where am I going wrong? This is the error it is giving me
Couldn't match type ‘Int’ with ‘Char’ Expected type: [Char] Actual
type: [Int]

The usual way to get a number from the user is to actually get a string from the user, then convert it to a number. Going from there to digits is just about the same thing as converting back to a string. I therefore recommend that you just skip the intermediate step and go straight from string to list of digits. If you want to reverse the digits and print them back out, say, just do that:
import Control.Monad
main = putStrLn . reverse =<< getLine
If you are going to use the digits for something else, you may want them in number form rather than character form; digitToInt will do that for you.
import Data.Char
main = map digitToInt <$> getLine -- exercise for the reader: do somethin' with the digits

Related

How to assign numbers 1-26 to letters a-z and then sum the output of a string in Haskell?

I'm tasked with writing a Haskell program that'll prompt the user to input a string, and then the program will assign a number to each letter(e.g. a = 1, d = 4, y = 25, z = 26) and then it will sum the total from the string. Example "Hi" would equal 8 + 9 or 17. I've got something to do the first part but only if its in all caps, but I still can't figure out how to get the output list summed.
import Data.Char
toOrder :: [Char] -> [Int]
toOrder str = map ((\x -> x - 64) . ord) str
Ideas?
You can use toUpper to regularize the characters, and sum to sum the list of Ints:
import Data.Char (ord, toUpper)
main = print $ score "Hi" -- 17
score :: String -> Int
score = sum . map (subtract 64 . ord . toUpper)

How to read/ add/ print a number string in Haskell

Below if my code right now. I want to be able to take in user input like the following: "6 1 2 3 4 5 6" and the get the sum and print. it would also be cool to understand how to use the first number entered as the total numbers. SO here the first number is 6 and the total numbers inputted is 6.
Thank you in advance for helping me with this. I have been researching for weeks and cannot figure this out.
main = do
putStrLn "Enter how many numbers:" -- clearer
num<-getLine
putStrLn("Enter a number: ")
numberString <- getLine
let numberInt =(read numberString :: Int)
print (numberInt*4)
main
It seems you either need an auxiliary recursive function for reading num integers, or some helper like replicateM, which makes writing the code a little easier.
replicateM num action runs action exactly num times, and collects all the action results in a list.
main = do
putStrLn "Enter how many numbers:" -- clearer
num<-getLine
numbers <- replicateM num $ do
putStrLn("Enter a number: ")
numberString <- getLine
return (read numberString :: Int)
-- here we have numbers :: [Int]
...
You can then continue from there.
If instead you want to use an auxiliary function, you can write
readInts :: Int -> IO [Int]
readInts 0 = return []
readInts n = do
putStrLn("Enter a number: ")
numberString <- getLine
otherNumbers <- readInts (n-1) -- read the rest
return (read numberString : otherNumbers)
Finally, instead of using getLine and then read, we could directly use readLn which combines both.
Construct a list of integers using
let l = map (\x -> read x::Int) (words "6 1 2 3 4 5 6")
in (numNumbers, numbers)
You tried to read the whole string into a single number.

How do I read N lines in a file with Haskell?

I have a file in the form:
3
1 2
3 4
5 7
Where the first line is the number of lines
I know that:
getInt :: IO Int
getInt = readLn
main = do num <- getInt
print (num)
Reads the first line.
Next, I tried:
readInts :: IO [Int]
readInts = fmap (map read.words) getLine
For read a line and get a list: [a,b].
And I tried to use the above in a recursive loop
loop :: Int -> IO()
loop n = if 1 == n then do num <- readInts
print(num)
else loop (n-1)
I'm getting the first line only:
[5,3]
But I need to read the rest of lines, given N
The format of the input file looks a lot like the ones used in programming contests. Here is my standard setup for programming contests like that:
import Control.Monad
import Text.Printf
main :: IO ()
main = do
n <- readLn
forM_ [1 .. n] $ \i -> do
printf "Case %d: " (i :: Int)
solve
An example of solve might be:
solve :: IO ()
solve = do
nums <- map read . words <$> getLine
print (sum nums)
Adding to this helpful answer and comment, for some challenges you'll need to collect n lines and then emit a single result at the end based on an aggregation of the data. An approach for creating a list might use replicateM as follows:
import Control.Monad
toInt :: String -> Int
toInt x = read x :: Int
lineToInts :: String -> [Int]
lineToInts x = map toInt $ words x
main :: IO ()
main = do
n <- readLn
remainingLines <- replicateM n getLine
let list = map lineToInts remainingLines
print list
Sample run:
3
0 1
3 4
6 8
[[0,1],[3,4],[6,8]]
See also Read n lines input with Haskell
Have you looked into the function lines? It takes a string and returns the same string as a list separated by \n. Using this function you don't even have to have the number of lines.

Haskell IO reads an integer n from the user then adds up n integers

I'm trying to write a program that reads an integer n from the user, then reads n integers (on separate lines), and finally display the sum of the n numbers read.
Here is my code so far:
addNumbers :: IO ()
addNumbers = do
putStrLn "Enter a number:"
num <- getInt
addNumbers2 num
addNumbers2 :: Int -> IO ()
addNumbers2 num = do
putStrLn "Enter a number:"
n <- getInt
if num == 1 then
print n
else do
print (n + addNumbers2 (num - 1))
At the moment it doesn't compile, the error says:
Couldn't match expected type `Int' with actual type `IO ()'
In the return type of a call of `addNumbers2'
In the second argument of `(+)', namely `addNumbers2 (num - 1)'
In the first argument of `print', namely
`(n + addNumbers2 (num - 1))'
IO is really confusing me, I'm trying to get an output of:
Enter a number:
3
Enter a number:
2
Enter a number:
1
Enter a number:
5
Sum is: 8
You treated addNumbers as if it were an ordinary function, but it's an IO operation, so we can only get numbers out of it inside do and with answer <- addNumbers2, but also at the moment it doesn't return anything, it just prints it.
I've refactored a little:
addNumbers :: IO ()
addNumbers = do
putStrLn "Enter how many numbers:" -- clearer
num <- getInt
sum <- addNumbers2 num -- use new version to return sum
print sum -- print them here
and now addNumbers2 actually adds them and returns them:
addNumbers2 :: Int -> IO Int
addNumbers2 num = do
putStrLn "Enter a number:"
n <- getInt
if num == 1 then
return n -- pass the number back
else do
therest <- addNumbers2 (num - 1) -- get the rest of them
return (n + therest) -- add them up
That works:
addNumbers
Enter how many numbers:
3
Enter a number:
1
Enter a number:
2
Enter a number:
3
6
A better way
sequence :: Monad m => [m a] -> m [a] takes a list of actions and runs them all, returning the list of results. If we just make a list full of getInts, [getInt| _<-[1..num]] or more consisely, replicate num getInt we could do numbers <- sequence (replicate num getInt). There's a shorthand for that in Control.Monad, called replicateM :: Monad m => Int -> m a -> m [a]
This would be better done like this though:
import Control.Monad
addNumbers' = do
putStrLn "Enter how many numbers:"
num <- getInt
numbers <- replicateM num (putStrLn "Enter a number" >> getInt)
print (sum numbers)
which gives
Enter how many numbers:
3
Enter a number
10
Enter a number
20
Enter a number
30
60
You can (and should) use combinators available
addNumbers2 n = do
n_numbers <- replicateM n (putStrLn "Number, please: " >> getInt)
let result = sum n_numbers
return result
The crucial insight is to combine the IO actions
putStrLn "string" :: IO ()
getInt :: IO Int
to
(putStrLn "Number?" >> getInt) :: IO Int
So we have a IO action that asks for input and reads it.
Now, we can use
replicateM :: Int -> IO a -> IO [a]
and since we pass an IO action that returns Int, we get a list of Int back.
numbers <- replicateM n (putStrLn "Number?" >> getInt)
runs the given IO action n times and collects their results.
All that is left is summing up the numbers and returning them in the IO Monad.
Or, if you just want to print the sum, you can also
replicateM n (putStrLn "Number?" >> getInt) >>= putStrLn . show . sum
The following pipes-based solution has one tiny advantage over the accepted solution, which is that it will not stack overflow on a large number of lines:
import Pipes
import qualified Pipes.Prelude as Pipes
main = do
numLines <- readLn
total <- Pipes.sum (Pipes.replicateM numLines readLn)
print total
Example use:
$ ./example
3<Enter>
10<Enter>
20<Enter>
30<Enter>
60

How can I print 2 elements with putStr Haskell?

I'm new to Haskell and I am wondering how can I print the results of two functions in Haskell, something I would do in c++ like:
cout << f() << g();
Or in c#:
Console.WriteLine(f() + " " + g());
In Haskell I tried something like
main =
--putStr ( show $ square 3 )
putStr ( show $ fibSeries 12 )
square :: Int -> Int
square x = x * x
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
fibSeries :: Int -> [Int]
fibSeries x = map fib [0..x]
but I had to comment the first command because it has given me a compile-time error.
The error is:
src\Main.hs:21:5:
Couldn't match expected type `(String -> IO ()) -> String -> t0'
with actual type `IO ()'
The function `putStr' is applied to three arguments,
but its type `String -> IO ()' has only one
In the expression:
putStr (show $ square 3) putStr (show $ fibSeries 12)
In an equation for `main':
main = putStr (show $ square 3) putStr (show $ fibSeries 12)
tl;dr You're so close!
main = do
putStr ( show $ square 3 )
putStr ( show $ fibSeries 12 )
Note that this won't put in any whitespace, you may wish to insert putStr " ".
Here's what's going on: Haskell's main part, the purely functional language, doesn't have any such thing as "order of computation / action". If you write two lines with statements like print 5, they're just parsed as one line, namely
print 5 print 5
which means the following: print is a function that takes the arguments 5, print, and 5, and returns the type of main (an IO action). So the type would need to be something like
type PrintType = Int -> PrintType -> Int -> IO()
which is of course nonsense. To tell Haskell you actually want to sequence a chain of actions (what you do all the time in imperative languages, but need much more seldom in functional programming), we have this nice do notation, which works a lot (but not always quite!) like you'd expect from an imperative standpoint.
To understand how that really works, you need to learn about monads. Those are explained in any decent Haskell tutorial. Read LYAH or something.
Further notes on your code: there's not much point in doing such a printing job sequentially, really. You can just produce a string with all the information you want, and then print that in one go:
main = putStrLn $ show (square 3) ++ " " ++ show (fibSeries 12)
or, if you're not so much interested in formatting but just in getting the information,
main = print ( square 3, fibSeries 12 )
which will result in the output (9,[0,1,1,2,3,5,8,13,21,34,55,89,144]).
Apart from do notation you can also use sequence_ function to execute a series of independent IO actions:
main = sequence_ [putStr $ show $ square 3 ,
putStr $ show $ fibSeries 12]

Resources