I am not able to print outputs in multiple lines with the following code.
average l = (sum l) / (fromIntegral (length l))
readDoubles s1 s2 = putStr (s1++"\n"++s2) >>
do x <- readDoublesHelper; return ("The average is " ++ (show (average x)) ++ " \n" ++ "The maximum is " ++ (show (maximum x)) ++ "\n" ++ "The minimum is " ++ (show (minimum x)) ++ "\n")
readDoublesHelper = putStr "Enter a number: " >>
do line <- getLine;
if line == "done"
then return [];
else do xs <- (readDoublesHelper)
return ((read line :: Float): xs)
interface = readDoubles "Enter some numbers." "When finished, type ’done’. \n"
The output that I get is
*Main> interface
Enter some numbers.
When finished, type ’done’.
Enter a number: 2
Enter a number: 3
Enter a number: 4
Enter a number: 5
Enter a number: 6
Enter a number: 7
Enter a number: done
"The average is 4.5 \nThe maximum is 7.0\nThe minimum is 2.0\n"
But I want the output to be printed like this
The average is 4.5
The maximum is 7.0
The minimum is 2.0
Do notice "The average is 4.5 \nThe maximum is 7.0\nThe minimum is 2.0\n" is actually not printed
Reformatting readDoubles:
readDoubles s1 s2 = do
putStr (s1++"\n"++s2)
x <- readDoublesHelper
return ("The average is " ++ (show (average x)) ++ " \n" ++ "The maximum is " ++ (show (maximum x)) ++ "\n" ++ "The minimum is " ++ (show (minimum x)) ++ "\n")
We can see that result is "returned" rather than "printed"
As the type signature of readDoubles is:
readDoubles :: String -> String -> IO String
It just returns a lifted string. Since GHCi will print out the final result of the function, you're getting "The average is 4.5 \nThe maximum is 7.0\nThe minimum is 2.0\n" as output (the return value of the function)
However, from you description, I guess you just like to print out the result, so it should be:
readDoubles :: String -> String -> IO ()
readDoubles s1 s2 = do
putStr (s1++"\n"++s2)
x <- readDoublesHelper
putStrLn ("The average is " ++ (show (average x)) ++ " \n" ++ "The maximum is " ++ (show (maximum x)) ++ "\n" ++ "The minimum is " ++ (show (minimum x)) ++ "\n")
Related
I am getting a parse error in my code and I don't know why. I can't see any problems with the code as it's the same syntax as pattern matching I have used in the past.
My code:
transaction_to_string (sob : unit : price : stock : day) :: Transaction
| sob == 'S' = "Sold " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
| sob == 'B' = "Bought " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
Where Transaction is a custom data type - Transaction = (Char, Int, Int, String, Int)
Error:
Parse error in pattern: transaction_to_string
|
23 | transaction_to_string (sob : unit : price : stock : day) :: Transaction
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are several syntax errors in your code example.
try this instead:
type Transaction = (Char, Int, Int, String, Int)
transaction_to_string :: Transaction -> String
transaction_to_string (sob, unit, price, stock, day)
| sob == 'S' = "Sold" ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
| sob == 'B' = "Bought " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
How can I write this code without repeating (c !! x) where is x = [0..7], using list comprehension is better but I couldn't figure how to write it
show (EOBoard f c r) = "EOBoard\n" ++ "Foundations "
++ show f ++ "\n" ++ "Columns \n"
++ show (c!!0) ++ "\n" ++ show (c!!1) ++ "\n"
++ show (c!!2) ++ "\n" ++ show (c!!3) ++ "\n"
++ show (c!!4) ++ "\n" ++ show (c!!5) ++ "\n"
++ show (c!!6) ++ "\n" ++ show (c!!7) ++ "\n"
++ "Reserves " ++ show r
Let's start by getting rid of all those manual line breaks.
import Data.List
show (EOBoard f c r) = intercalate "\n" $
[ "EOBoard"
, "Foundations " ++ show f
, "Columns"
, show (c!!0)
, show (c!!1)
, show (c!!2)
, show (c!!3)
, show (c!!4)
, show (c!!5)
, show (c!!6)
, show (c!!7)
, "Reserves " ++ show r]
Note: if you want a line break at the end too, use unlines instead of intercalate.
As you noticed, there's a rather repetitive section. Also, those !! applications are kind of expensive. A list comprehension solves both problems, but I'd use map instead.
show (EOBoard f c r) = intercalate "\n" $
[ "EOBoard"
, "Foundations " ++ show f
, "Columns" ] ++
map show c ++
["Reserves " ++ show r]
(map show c could be replaced by [show x | x <- c] if you prefer.)
There's still something funny; Show really isn't for pretty-printing. show shouldn't insert line breaks. You probably actually want to write a custom pretty-printing function instead.
What you wrote is equivalent to
show (EOBoard f c r) = "EOBoard\n" ++ "Foundations "
++ show f ++ "\n" ++ "Columns \n" ++
++ concat [ show s ++ "\n" | s <- take 8 c]
++ "\n" ++ "Reserves " ++ show r
which is equivalent to
show (EOBoard f c r) = "EOBoard\n" ++ "Foundations "
++ show f ++ "\n" ++ "Columns \n" ++
++ [ ch | s <- take 8 c, ch <- show s ++ "\n" ]
++ "\n" ++ "Reserves " ++ show r
or, using the concat more instead of inlining it, it is equivalent to
show (EOBoard f c r) = concat (
[ "EOBoard\n", "Foundations ", show f, "\n", "Columns \n" ]
++ [ show s ++ "\n" | s <- take 8 c]
++ ["\n" , "Reserves " , show r] )
which is normally written with the $ operator, as
show (EOBoard f c r) = concat $
[ "EOBoard\n", "Foundations ", show f, "\n", "Columns \n" ]
++ [ show s ++ "\n" | s <- take 8 c]
++ ["\n" , "Reserves " , show r]
In the following code, line 4, I have an expression sandwiched between two IO actions in a do block:
1 doubleX :: (Show x, Num x) => x -> IO ()
2 doubleX x = do
3 putStrLn ("I will now double " ++ (show x))
4 let double = x * 2
5 putStrLn ("The result is " ++ (show double))
I understand do notation as chaining monadic operations together using >>= or >>. But how does that work when you have an expression in between? You couldn't just glue lines 3-5 together using >>.
I'm going to crib from my very similar answer here (though probably not a duplicate since that question doesn't explicitly deal with let).
The Report gives a full translation from do syntax into kernel Haskell; the parts relevant to your question are:
do {e} = e
do {e;stmts} = e >> do {stmts}
do {let decls; stmts} = let decls in do {stmts}
So your code desugars like this:
doubleX x = do
putStrLn ("I will now double " ++ (show x))
let double = x * 2
putStrLn ("The result is " ++ (show double))
==> do {e;stmts} rule
doubleX x =
putStrLn ("I will now double " ++ (show x)) >> do
let double = x * 2
putStrLn ("The result is " ++ (show double))
==> do {let decls; stmts} rule
doubleX x =
putStrLn ("I will now double " ++ (show x)) >>
let double = x * 2 in do
putStrLn ("The result is " ++ (show double))
==> do {e} rule
doubleX x =
putStrLn ("I will now double " ++ (show x)) >>
let double = x * 2 in
putStrLn ("The result is " ++ (show double))
I have written the following to assist grand kids with their home schooling work and to keep mind working by learning how to program (I thought haskell sounded awesome).
main :: IO ()
main = do
putStrLn "Please enter the dividend :"
inputx <- getLine
putStrLn "Please enter the divisor :"
inputy <- getLine
let x = (read inputx) :: Int
let y = (read inputy) :: Int
let z = x `div` y
let remain = x `mod` y
putStrLn ( "Result: " ++ show x ++ " / " ++ show y ++ " = " ++ show z ++ " remainder " ++ show remain )
putStrLn ( "Proof: (" ++ show y ++ " x " ++ show z ++ ") = " ++ show (y * z) ++ " + " ++ show remain ++ " = " ++ show ((y * z) + remain))
putStrLn ( "Is this what you had? ")
Is their a neater/nicer/better/more compact way of doing this?
It would benefit from a key principle: separate your pure code from your IO as much as possible. This will let your programs scale up and keep main breif. Lots of let in a big main isn't a very functional approach and tends to get much messier as your code grows.
Using a type signature and readLn which is essentially fmap read getLine helps cut down some cruft. (If you're not familiar with fmap, visit the question How do functors work in haskell?. fmap is a very flexible tool indeed.)
getInts :: IO (Int, Int)
getInts = do
putStrLn "Please enter the dividend :"
x <- readLn
putStrLn " Please enter the divisor :"
y <- readLn
return (x,y)
Now the processing. If I were doing more with this kind of data, or more frequently, I'd be using a record type to store the dividend, divisor, quotient and remainder, so bear that in mind for the future, but it's an overkill here.
I'm hackishly returning a list rather than a tuple, so I can use map to show them all:
sums :: (Int, Int) -> [Int]
sums (x,y) = [x, y, q, r, y * q, y * q + r] where
q = x `div` y
r = x `mod` y
The final piece of the jigsaw is the output. Again I prefer to generate this outside IO and then I can just mapM_ putStrLn on it later to print each line. I'd prefer this to take the record type, but I'm tolerating a list of strings as input instead since I'm assuming I've already shown them all.
explain :: [String] -> [String]
explain [x,y,q,r,yq,yq_r] =
[ concat ["Result: ", x, " / ", y, " = ", q, " remainder ", r]
, concat ["Proof: (", y, " x ", q, ") + ", r, " = ", yq, " + ", r, " = ", yq_r]
, "Is this what you had? "]
Now we can write main as
main = do (x,y) <- getInts
let ns = map show ( sums (x,y) )
es = explain ns
mapM_ putStrLn es
or even more succinctly, by piping together the functions explain . map show . sums, and applying that to the output of getInts using fmap:
main :: IO ()
main = fmap (explain . map show . sums) getInts
>>= mapM_ putStrLn
You might notice that I added a +r in the proof to make = always mean =, which is the correct mathematical usage, and mirror's Haskell's meaning for =.
I have a list of tuples. For example: [("A",100,1),("B",101,2)]. I need to display it in a simple way. For example: "your name is: A", "Your id is: 100".
If anyone can find a solution for this, it would be a great help. Thanks in advance.
The easiest way to do this is to create a function that works for one of the elements in your list. So you'll need something like:
showDetails :: (String, Int, Int) -> String
showDetails (name, uid, _) = "Your name is:" ++ name ++ " Your ID is: " ++ show uid
Then you would apply this function to each element in the list, which means you want to use the mapping function:
map :: (a -> b) -> [a] -> [b]
So, if your list is called xs, you would want something like:
map showDetails xs
This obviously gives you a result of type [String], so you might be interested in the unlines function:
unlines :: [String] -> String
This simply takes a list of strings, and creates a string where each element is separated by a new line.
Putting this all together, then, gives you:
main :: IO ()
main = putStrLn . unlines . map showDetails $ [("A",100,1),("B",101,2)]
For a single tuple, just pattern match all the elements, and do something with them. Having a function that does that, you can use map to transform the entire list.
import Data.List (foldl')
show_tuple :: (Num a, Num b) => (String, a, b) -> String
show_tuple (name, id, something) =
"Your name is: " ++ name ++ "\n" ++
"Your ID is: " ++ (show id) ++ "\n" ++
"Your something: " ++ (show something) ++ "\n\n"
-- transforms the list, and then concatenates it into a single string
show_tuple_list :: (Num a, Num b) => [(String, a, b)] -> String
show_tuple_list = (foldl' (++) "") . (map show_tuple)
The output:
*Main Data.List> putStr $ show_tuple_list [("ab", 2, 3), ("cd", 4, 5)]
Your name is: ab
Your ID is: 2
Your something: 3
Your name is: cd
Your ID is: 4
Your something: 5
Quick and dirty solution
f (x,y,z) = "your id is " ++ (show y) ++ ", your name is " ++ (show x) ++ "\n"
main = putStrLn $ foldr (++) "" (map f [("A",100,1),("B",101,2)])
OR (by #maksenov)
main = putStrLn $ concatMap f [("A",100,1),("B",101,2)]
Please try:
get1st (a,_,_) = a
get2nd (_,a,_) = a
get3rd (_,_,a) = a
showTuples [] = ""
showTuples (x:xs) = "Your name is:" ++ show(get1st(x)) ++ " Your ID is: " ++ show(get2nd(x)) ++ "\n" ++ showTuples xs
main = do
let x = [("A",100,1),("B",101,2)]
putStrLn . showTuples $ x