I'm very much a beginner at Haskell and I've hit a rather annoying bump in the road. At my current stage I am just trying to pass a lists from my main function into another and just PRINT it and I don't understand why it wont work.
In my head, I feel like I should just be able to:
main = do
putStrLn "-----Text Editor-----"
putStrLn "Please enter your text"
leftString <- getLine
putStrLn $ "\n\n" ++ leftString ++ "|"
moveCursorLeft = do
putStr $ leftString
but this doesn't seem to work as 'leftString' is not in scope.
Function calls are a handshake between caller and callee: the caller must pass some arguments, and the callee must accept them. As you've written it, moveCursorLeft doesn't accept any arguments. But don't worry, it's easy to fix:
moveCursorLeft leftString = do
putStr $ leftString
You could now use this in main, e.g.
main = do
leftString <- getLine
putStr "\n\n"
moveCursorLeft leftString
putStrLn "|"
Related
I am writing a palindrome solution in Haskell, and I want the function to show an error if a null is entered. I do not want to use the error function as that halts the program. Hence, I want to show an error message using putStrLn and continue the loop.
I have tried using show to change the input given to the putStrLn but it doesn't work and throws compile time type-error.
main = do
putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
word <- getLine
if null word
then
-- putStrLn "This is not a word!"
main
else do
putStrLn $ show $ checkPalindrome word
main
checkPalindrome w = if reverse w == w then True else False
I expect it to show an error, but it only gives an error. What are possible solutions to show a halt-safe error?
If you write both a putStrLn "this is not a word!" and a main, you should use a do block here:
main = do
putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
word <- getLine
if null word
then do
putStrLn "This is not a word!"
main
else do
putStrLn $ show $ checkPalindrome word
main
That being said, you can simplify the above by making a call at the bottom of the do block of the main:
main = do
putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
word <- getLine
if null word
then putStrLn "This is not a word!"
else putStrLn $ show $ checkPalindrome word
main
or we can, like #Bergi says, even put more in the main block, like:
main = do
putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
word <- getLine
putStrLn $ if null word
then "This is not a word!"
else show $ checkPalindrome word
main
If you write this without do block, Haskell aims to parse putStrLn "This is not a word!" main. This thus means that putStrLn is supposed to have type String -> IO a -> IO a, but that is not the case.
By using a do block, Haskell will desugar the do block [Haskell'10 report] into putStrLn "This is not a word!" >> main, and this is sound (at least for the type system). Since the bind operator has type (>>) :: Monad m => m a -> m b -> m b.
I'm trying to deal with IO actions. I wonder why does this work:
main = do
alias = getLine
name <- alias
putStrLn ("your name is: " ++ name)
saying
parse error on input `='
Add keyword let
main = do
let alias = getLine
name <- alias
putStrLn ("your name is: " ++ name)
do is a specified construction for monadic bind operator, it's not a cosmic space. All you write into block do is really chain of >>= monaidic functions. So you should use let construction.
But you can make alias in other part of you program.
alias = getLine
main = do
name <- alias
putStrLn ("your name is: " ++ name)
I currently have an application which has a menu which will execute the following functions: add, remove and view. What I would like to know is how can I reference code as a function.
The code I am trying to reference is like this:
putStrLn "Please enter the username:"
addName <- getLine
appendFile "UserList.txt" ("\n" ++ addName)
Would I have to use a let function? For example:
let addUserName =
putStrLn "Please enter the username:"
addName <- getLine
appendFile "UserList.txt" ("\n" ++ addName).
First of all, you use the let keyword when you're in GHCi because you're in the IO monad. You normally wouldn't need it to define a function in source code. For example, you could have a file called "MyProgram.hs" containing:
addUserName = do
putStrLn "Please enter the username:"
addName <- getLine
appendFile "UserList.txt" ("\n" ++ addName)
Then in GHCi, you type:
ghci> :l MyProgram.hs
ghci> addUserName
(That's :l for :load, not the numeral one.) Actually, you can define a function in GHCi, but it's a bit of a pain unless it's a one-liner. This would work:
ghci> let greet = putStrLn "Hello!"
ghci> greet
Hello!
I'm a Haskell beginner, I'm just beginning to wrap my head around Monads, but I don't really get it yet. I'm writing a game that consists of asking the user for input, and responding. Here is a simplified version of my function:
getPoint :: IO Point
getPoint = do
putStr "Enter x: "
xStr <- getLine
putStr "Enter y: "
yStr <- getLine
return $ Point (read xStr) (read yStr)
completeUserTurn :: (Board, Player) -> IO (Board, Player)
completeUserTurn (board, player) = do
putStr $ "Enter some value: "
var1 <- getLine
putStr $ "Enter another value: "
var2 <- getLine
putStr $ "Enter a point this time: "
point <- getPoint
if (... the player entered legal values ...) then do
putStr $ "This is what would happen if you did that: {stuff} do you want to do that? (y/n) "
continue <- getLine
if continue == "y" then
return (...updated board..., ...updated player...)
else
completeUserTurn (board, player)
else do
putStr "Invalid Move!\n"
completeUserTurn (board, player)
What's happening is that the prompts will appear out of order with the text that is supposed to appear before the prompt.
Here's an example of what's happening after I compiled the code above:
1
Enter some value: Enter another value:2
3
4
Enter a point this time: Enter x: Enter y: y
Is this correct? (y/n):
The bold are the things I typed in.
Obviously, I have some major conceptual error, but I don't know what. Note that it works correctly in the interpreter and fails when compiled.
As Michael said, the issue is buffering. By default, output is buffered until you print a newline (or until the buffer is full if you have really long lines), so you'll most often see this issue when trying to do same-line prompts using putStr like you're doing.
I suggest defining a small helper function like this to take care of doing the flushing for you:
import System.IO
prompt :: String -> IO String
prompt text = do
putStr text
hFlush stdout
getLine
Now you can simply do
getPoint = do
xStr <- prompt "Enter x: "
yStr <- prompt "Enter y: "
return $ Point (read xStr) (read yStr)
The IO is happening in the correct order. The issue is buffering. If you flush stdout after each putStr, it should work as expecting. You'll need to import hFlush and stdout from System.IO.
The problem wasn't with the order of operations in the IO code. The issue was input and output is by default buffered when using stdin and stdout. This increases the performance of IO in an app, but can cause operations to appear to occur out of order when both stdin and stdout are used.
There is two solutions to this. You can use the hFlush method to force a handle (either stdin or stdout) to be flushed. Eg hFlush stdout, hFlush stdin. A simpler solution (which works fine for interactive apps) is to disable buffering altogether. You can do this by calling the methods hSetBuffering stdout NoBuffering and hSetBuffering stdin NoBuffering before you start your program (ie put those lines in your main method.
In Haskell, is it possible to share user input from one IO function to the other?
For instance, if I had:
main = do
putStrLn "Give me a number!"
my_stuff <- getLine
let nump = read (my_stuff)::Int
another_function nump
Where another_function is also an IO function with a do construct.
another_function nump = do
putStrLn nump
putStrLn "Try again!"
main
This would make sense in the fantasy-world Haskell interpreter I have in my head. However, in the real world: my_stuff is unbound in another_function; and in main, my_stuff requires to be of type IO t but it isn't.
The above code would (most probably) be very offensive to Haskellers, yet I hope that it conveyed what exactly I'm aiming for...
How do I work around this?
This code works. Is this what you want to do? If not, can you provide with the code that doesn't work?
main = do
putStrLn "Give me a number!"
my_stuff <- getLine
let nump = read (my_stuff)::Int
another_function nump
another_function nump = do
putStrLn $ show nump
putStrLn "Try again!"
main