I'm trying to make a simple function that gets 2 variables from the user (x,y)
makes a calculation, and prints it out.
for some reason without success:
main = do
putStrLn "Insert Number1"
x <- readLn
putStrLn "Insert Number2"
y <- readLn
z = (x * y * 0.01)
putStrLn "Result: " ++z
The Error I get:
test.hs:6:11: parse error on input `='
Use let to bind new variables. You also have a few errors on the final line: first, you must explicitly convert between Double and String (using, for example, show), and secondly, you need to remember precedence. In Haskell, function application binds tighter than anything except record updates, so what you wrote parses as (putStrLn "Result: ") ++ z, which doesn't really make sense. With these things fixed:
main = do
putStrLn "Insert Number1"
x <- readLn
putStrLn "Insert Number2"
y <- readLn
let z = x * y * 0.01
putStrLn ("Result: " ++ show z)
Related
Can't get my haskell program to work
sort [] = []
sort (x:xs) = sort [a | a <- xs , a<=x ] ++ [x] ++ sort [a | a <- xs , a > x]
getList:: Int->[IO Int]
getList 0 = [] --declaring the empty list
getList n = [a | a <- [getNumber] ] ++ getList (n-1)
getNumber::IO Int --get number function
getNumber = do
s <- getLine
return (read s)
--Main function to handle
main = do
p <- getNumber -- taking the number of variable
lst <- sequence (getList p) --calling gtlistFunction to input the list
print (sort lst) --print
Error:
quicksort.hs:13:6: error:
parse error on input `='
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
|
13 | main = do
| ^
You must indent all do-blocks:
-- NOT correct: this will fail
main = do
putStrLn "This is..."
putStrLn "WRONG!"
-- Correct:
main = do
putStrLn "This is..."
putStrLn "correct!"
The number of spaces doesn't matter as long it is consistent.
To avoid this you could use c-like notation:
-- Also correct:
main = do {
putStrLn "This is...";
putStrLn "also correct!";
}
And this leaves you free to indent as you like. Example:
-- Also correct:
main = do
{ putStrLn "This is..."
; putStrLn "also correct!"
;}
Without indentation, the parser doesn't know that main = ... starts a new definition, separate from the preceding definition of getNumber. The following would work fine:
getNumber::IO Int
getNumber = do
s <- getLine
return (read s)
main = do
p <- getNumber
lst <- sequence (getList p)
print (sort lst)
The transition from one-space indentation to no indentation is enough to tell the parser that return (read s) is the last line of the do block defining getNumber, and that main = do is the beginning of a new top-level definition.
Either indenting your code, or using the explicit brace syntax in AJFarmar's answer, lets the parser know where one definition ends and the next begins.
Can anyone tell me why I cannot add a IO statement within a do block? This code only prints "test" and then completes execution. The last two lines do not seem to be executing.
putStrLn "Do you want to add a task. Press y to add:"
option <- getChar
when (option == 'y') $ do
print "test"
newText <- getLine
appendFile "todoList.txt" (newText ++ "\n")
getChar will peak the y char but will let the \n in the input stream.
So you need to flush the input stream before going further.
Alternatively you can use the readLn providing you define a new data type:
data Choice = Y | N
deriving (Read, Show, Eq)
putStrLn "Do you want to add a task. Press y to add:"
option <- readLn
when (option == Y) $ do
print "test"
getLine >>= appendFile "todoList.txt" . (++"\n")
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 =.
At the moment, I have this code in and around main:
import Control.Monad
import Control.Applicative
binSearch :: Ord a => [a] -> a -> Maybe Int
main = do
xs <- lines <$> readFile "Cars1.txt"
x <- getLine <* putStr "Registration: " -- Right?
putStrLn $ case binSearch xs x of
Just n -> "Found at position " ++ show n
Nothing -> "Not found"
My hope is for “Registration: ” to be printed, then for the program to wait for the input to x. Does what I've written imply that that will be the case? Do I need the <*, or will putting the putStr expression on the line above make things work as well?
PS: I know I have to convert binSearch to work with arrays rather than lists (otherwise it's probably not worth doing a binary search), but that's a problem for another day.
The line
x <- getLine <* putStr "Registration: "
orders the IO actions left-to-right: first a line is taken as input, then the message is printed, and finally variable x is bound to the result of getLine.
Do I need the <*, or will putting the putStr expression on the line
above make things work as well?
If you want the message to precede the input, you have to put the putStr on the line above, as follows:
main :: IO ()
main = do
xs <- lines <$> readFile "Cars1.txt"
putStr "Registration: "
x <- getLine
putStrLn $ case binSearch xs x of
Just n -> "Found at position " ++ show n
Nothing -> "Not found"
Alternatively,
x <- putStr "Registration: " *> getLine
or
x <- putStr "Registration: " >> getLine
would work, but they are less readable.
Finally, since you added the lazy-evaluation tag, let me add that your question is actually not about laziness, but about how the operator <* is defined, and in particular about the order in which it sequences the IO actions.
Sorry for a poor title, feel free to edit. I can't understand what the problem is, so it might be altogether wrong. Below is the code (this is after I've done like a hundred of permutations and different sequences of let-do-if and tabulation, and I'm exhausted):
-- The last statement in a 'do' construct must be an expression
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n"
let intYear = readYear
in if (intYear < 2000 || intYear > 2012)
then error "Year must be withing range: 2000-2012"
else
c <- readIORef connection
[Only i] <- query_ c ("select count('*')" ++
"from table" ++
"where ((acquisition_date <= " ++
(formatDate intYear) ++
") and ((sale_date is null) or " ++
"(sale_date < " ++
(formatDate intYear) ++ ")))")
return i
readYear :: Integer
readYear = do
year <- getLine
read year :: Integer
Something that would meant to be so simple... I still don't understand what is wrong with the code above. Please, if you could kindly explain the source of the error, that would be great.
I did read about do, let-in and if-then-else, and I don't see any errors here from what I could understand from the manual.
Ideally, if there are alternatives, I would like very much to reduce the amount of the wasted white space on the left.
Thank you.
readYear is not an Integer, it's an IO action that can be run to read input and convert the input to an integer -- in other words, IO Integer. And as it's an IO action, you'll need a return to use whatever read year as result of getYear. That is:
getYear :: IO Integer
getYear = do year <- getLine
return (read year)
This also means you use it like intYear <- readYear instead of using let (well, you could, but you'd store the IO action instead of running it, and the type of intYear would be wrong). That is:
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n"
intYear <- readYear
...
do does not extend over if, rather you need to start again with do if you want a sequence of actions in the then or else branch. That is:
else
c <- readIORef connection
...
return i
should be roughly:
else do c <- readIORef connection
...
return i
As for reducing whitespace, consider pushing the validation logic into readYear. Implementing this is left as an exercise to the reader ;)
As an aside, you don't need in when using let in a do block (but only there!), you can simply state:
do do_something
let val = pure_compuation
something_else_using val
You need a new do for every block of monadic functions: simply writing functions in a row has no meaning, regardless of whether they're monadic or pure. And everything where the value comes from the IO monad must itself give its return value in the monad.
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n" -- why extra '\n'?
intYear <- readYear -- readYear expects user input <- must be monadic
if (intYear < 2000 || intYear > 2012)
then error "Year must be withing range: 2000-2012"
else do
c <- readIORef connection
[Only i] <- query_ c ("select count('*')" ++
"from table" ++
"where ((acquisition_date <= " ++
(formatDate intYear) ++
") and ((sale_date is null) or " ++
"(sale_date < " ++
(formatDate intYear) ++ ")))")
return i
readYear :: IO Integer
readYear = do
year <- getLine
return $ read year :: Integer
Why is an extra do needed...
Well, the thing with do in Haskell is that it's really just syntactic sugar. Let's simplify your function a little
nOG :: IO String
nOG = do putStrLn "Prompt"
someInput <- inputSth
if condition someInput
then error "Bloap"
else do c <- inputSthElse
[only] <- query_ c
return only
what this actually means is
nOG :: IO String
nOG = putStrLn "Prompt"
>> inputSth
>>= (\someInput ->
if condition someInput
then error "Bloap"
else inputSthElse
>>= (\s -> query_ c
>>= (\[only] -> return only )
)
)
Where you should be able to see that if behaves in exactly the same way as it does in a pure functional expression like shade (r,g,b) = if g>r && g>b then "greenish" else "purpleish". It doesn't in any way "know" about all the IO monad stuff going on around it, so it can't infer that there should again be a do block in one of its branches.