Haskell how can I show function result - haskell

I have a question that asks me find 'quadratic equation' and show result and add number of the roots
example:
Main> quadratric 2 2 2
2x^2 + 2x + 2 = 0
Has no real roots.
Main> quadratic 2 5 2
2x^2 + 5x + 2 = 0
Has two real roots:
-2.0 and -0.5
So this is quadratic equation:
quadraticprob a b c
| root < 0 = error "Has no real roots"
| root == 0 = [-b/(2*a)]
| root > 0 = [-b/(2*a) + sqroot/(2*a),
-b/(2*a) - sqroot/(2*a)]
where
root = b*b - 4*a*c
sqroot = sqrt root
I can get the result but I should add how many roots they have so I should use one more function that getLine and show the result.
I made this but it's totally wrong:
readresult :: IO ()
readresult = do
line <- getLine
putStrLn (show (quadraticprob (read line))
Can you help me with my mistake please?

Assume you want get 3 integers from standard input call "getLine" function once.
The expression
line <- getLine
will return a string like (for example)
"2 2 2"
with spaces between each integer. The first thing need to do is to remove the space and convert it from string to Int type. the words and read functions can solve this easily as below:
map read (words line)::[Int]
However, a integers list cannot pass to your quadratic function directly, it need use case get elements from list as below
case map read (words line)::[Int] of
[a, b, c] -> putStrLn $ show $ quadraticprob a b c
If you want read real number instead of integers, just change map..::[Int] to ::[Double].

A few hints:
Use a getLine for each argument
... = do
astr <- getLine
bstr <- getLine
cstr <- getLine
putStrLn (show (quadraticprob (read astr) (read bstr) (read cstr)))
For quadraticprob, it's not clear what your goal actually is. Before writing any code, you should start by writing the intended type.
quadraticprob :: ?? -> ?? -> ?? -> ??
What should that be?

Related

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.

Haskell: Print case number

I have written a Haskell code as:
loop = do
x <- getLine
if x == "0"
then return ()
else do arr <- replicateM (read x :: Int) getLine
let blocks = map (read :: String -> Int) $ words $ unwords arr
putStr "Case X : output = "; -- <- What should X be?
print $ solve $ blockPair blocks;
loop
main = loop
This terminates at 0 input. I also want to print the case number eg. Case 1, 2 ...
Sample run:
1
10 20 30
Case 1: Output = ...
1
6 8 10
Case 2: Output = ...
0
Does anyone know how this can be done? Also, If possible can you suggest me a way to print the output line at the very end?
Thanks in advance.
For the first part of your question, the current case number is an example of some "state" that you want to maintain during the course of your program's execution. In other languages, you'd use a mutable variable, no doubt.
In Haskell, there are several ways to deal with state. One of the simplest (though it is sometimes a little ugly) is to pass the state explicitly as a function parameter, and this will work pretty well given the way you've already structured your code:
main = loop 1
loop n = do
...
putStr ("Case " ++ show n ++ ": Output = ...")
...
loop (n+1) -- update "state" for next loop
The second part of your question is a little more involved. It looks like you wanted a hint instead of a solution. To get you started, let me show you an example of a function that reads lines until the user enters end and then returns the list of all the lines up to but not including end (together with a main function that does something interesting with the lines using mostly pure code):
readToEnd :: IO [String]
readToEnd = do
line <- getLine
if line == "end"
then return []
else do
rest <- readToEnd
return (line:rest)
main = do
lines <- readToEnd
-- now "pure" code makes complex manipulations easy:
putStr $ unlines $
zipWith (\n line -> "Case " ++ show n ++ ": " ++ line)
[1..] lines
Edit: I guess you wanted a more direct answer instead of a hint, so the way you would adapt the above approach to reading a list of blocks would be to write something like:
readBlocks :: IO [[Int]]
readBlocks = do
n <- read <$> getLine
if n == 0 then return [] else do
arr <- replicateM n getLine
let block = map read $ words $ unwords arr
blocks <- readBlocks
return (block:blocks)
and then main would look like this:
main = do
blocks <- readBlocks
putStr $ unlines $
zipWith (\n line -> "Case " ++ show n ++ ": " ++ line)
[1..] (map (show . solve . blockPair) blocks)
This is similar in spirit to K. A. Buhr's answer (the crucial move is still passing state as a parameter), but factored differently to demonstrate a neat trick. Since IO actions are just normal Haskell values, you can use the loop to build the action which will print the output without executing it:
loop :: (Int, IO ()) -> IO ()
loop (nCase, prnAccum) = do
x <- getLine
if x == "0"
then prnAccum
else do inpLines <- replicateM (read x) getLine
let blocks = map read $ words $ unwords inpLines
prnAccumAndNext = do
prnAccum
putStr $ "Case " ++ show nCase ++ " : output = "
print $ solve $ blockPair blocks
loop (nCase + 1, prnAccumAndNext)
main = loop (1, return ())
Some remarks on the solution above:
prnAccum, the action which prints the results, is threaded through the recursive loop calls just like nCase (I packaged them both in a pair as a matter of style, but it would have worked just as fine if they were passed as separate arguments).
Note how the updated action, prnAccumAndNext, is not directly in the main do block; it is defined in a let block instead. That explains why it is not executed on each iteration, but only at the end of the loop, when the final prnAccum is executed.
As luqui suggests, I have removed the type annotations you used with read. The one at the replicateM call is certainly not necessary, and the other one isn't as well as long as blockPair takes a list of Int as an argument, as it seems to be the case.
Nitpicking: I removed the semicolons, as they are not necessary. Also, if arr refers to "array" it isn't a very appropriate name (as it is a list, and not an array), so I took the liberty to change it into something more descriptive. (You can find some other ideas for useful tricks and style adjustments in K. A. Buhr's answer.)

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]

How can I use map with a string got from getLine?[Haskell]

I want to read a String and toUpper all the characters.
import Data.Char
main = do
a <- getLine
b <- getLine
map toUpper a
if (a == b)
then print 0
else if (a < b)
then print (-1)
else print 1
Then I got this
Couldn't match expected type `IO a0' with actual type `[b0]'
In the return type of a call of `map'
In a stmt of a 'do' expression: map toUpper a
In the expression:
do { a <- getLine;
b <- getLine;
map toUpper a;
if (a == b) then
print 0
else
if (a < b) then print (- 1) else print 1 }
Hou can I use map with a String got from getLine?
Or there is another way to read a String and toUpper all the characters ?
You are not assigning the "result" of your map call to anything at all. This is causing the type error you are getting, which is telling you that you are trying to return a string (the result of the map call), when it really needs to be some IO type.
A direct fix would look something like this:
import Data.Char
main = do
a <- getLine
b <- getLine
let c = map toUpper a
if (c == b)
then print 0
else if (c < b)
then print (-1)
else print 1
If you use fmap you can toUpper all the chars and get the line of input at the same time (preventing the need for a c).
import Data.Char
main = do
a <- fmap (map toUpper) getLine
b <- getLine
if a == b
then print 0
else if a < b
then print (-1)
else print 1
Others have corrected your program in the minimal way, but I want to point out a C-ism that Haskell has improved:
if (a == b)
then print 0
else if (a < b)
then print (-1)
else print 1
Has it ever bothered you that numbers were appropriated for recording how a thing compared? It's certainly bothered me. Fortunately, defining new data types in Haskell is so cheap that we do it all the time. In the standard library, there's a type defined as follows:
data Ordering = LT | EQ | GT
And there's a standard function
compare :: Ord a => a -> a -> Ordering
So why not use this beautiful Haskell artifact?
main = do
a <- getLine
b <- getLine
print (compare (map toUpper a) b)
in Haskell it's a good practice to separate non-monadic code from monadic one.
A very minimal improvement is to move print outwards:
print $ if (a == c)
then 0
else if (a < b)
then (-1)
else 1
As for an idiomatic solution, think of separating all non-monadic code in a separate function (both comparison and uppercasing).
Also, if you see elsif in your code, think about guards:
c_compare a c
| a == c = 0
| a < c = -1
| otherwise = 1
A case implementation is also possible:
c_compare a c = case (compare a c) of
LT -> -1
EQ -> 0
GT -> 1
Remember, everything in Haskell is immutable, so calling map toUpper a doesn't actually modify a. If you'd like to save that result, you'll have to bind it to a variable in a let clause. So you might want to change your code to something like this:
import Data.Char
main = do
a <- getLine
b <- getLine
let c = map toUpper a
if (a == c)
then print 0
else if (a < b)
then print (-1)
else print 1

Help In Solving Problem Using Guards - UPDATED With CODE

I am using guards inside a function but not immediately after the function signature. The guards are under a do statement inside the body of the function. I get this error:
parse error on input `|'
I thought maybe the error comes from the indentation but i have tried many indentation but still i get the errors. Am asking is it because the guards are not immedaitely after the function signature that is why am getting the errors?
thanks
UPDATE 1
CODE:
The user is suppose to guess a number , and the number will be compared with the random number if they are the same. If it is not correct then the user will guess till the "guess" variable in the function is zero. in every interation that value(guess) is decreased by one.
for instance : puzz 12 5. the user can guess for five times, the random number will be picked between 1 and 12. that is how the function is suppose to do, but it is not working.
puzz :: Int -> Int -> IO ()
puzz boundary guess = do
putStr "Guess"
-- putStr -- I have to print (1 .. guess) here in each iteration
putStr ":"
x <- randomRIO (1, boundary :: Int)
n <- getLine
let
nTo = read n::Int
in print x
| guess == 0 = putStr "You couldn't guess right,the correct answer is" ++ x
| nTo > x = putStr "lower"
| nTo < x = putStr "higer"
| nTo == x = putStr "Congrat, You guess right."
| otherwise raad boundary (guess - 1)
the ouput must be like this:
Main> puzz 50 6
Guess a number betwee 1 en 50.
Guess 1: 49
lower
Guess 2: 25
lower
Guess 3: 12
higher
Guess 4: 18
higher
Guess 5: 21
higher
Guess 6: 23
lower
You couldn't guess correct, the answer was: 22.
thanks for your help
You’re using guards incorrectly. From the report:
Top level patterns in case expressions and the set of top level patterns in function or pattern bindings may have zero or more associated guards.
So they’re only for cases and function bindings. If you just want to concisely introduce a series of true-false tests, while inside a do-notation, perhaps the case () of () trick would work:
main = do
putStrLn "hello world"
n <- getLine
let nTo = read n :: Int
case ()
of () | cond -> putStrLn "foo"
| cond' -> putStrLn "bar"
| otherwise -> putStrLn "baz"
It should be noted that there are several things that are a bit off with your code, in addition to using guards wrong. By default output is buffered in haskell so if you want Guess to be on the same line as input you have to either say that stdOut should not be buffered (hSetBuffering stdOut NoBuffering), or you have to flush output with hFlush. It's not necessary to write boundary :: Int, the compiler knows it is an Int. Here is a bit more complete example, I'm sure it could be done better but atleast it works:
import Control.Monad(liftM,unless)
import System.IO(hFlush,stdout)
import System.Random(randomRIO)
guessMyNumber upper guesses = do
putStrLn $ "Guess a number between 1 and " ++ show upper ++ "!"
randomRIO (1, upper) >>= puzz guesses
puzz 0 number = do
putStrLn $ "Sorry, no more guesses, the number was "
++ show number ++ "."
puzz guesses number = do
putStr "Guess:" >> hFlush stdout
guess <- liftM read getLine
printMessage guess number guesses
printMessage guess number guesses
| number > guess = putStrLn "higer" >> puzz (guesses-1) number
| number < guess = putStrLn "lower" >> puzz (guesses-1) number
| number == guess = putStrLn "Congratulations! You guessed right!"

Resources