Deleting items in stdin with haskell - haskell

I have a bit of code in my haskell program like so:
evaluate :: String -> IO ()
evaluate = ...
repl = forever $ do
putStr "> " >> hFlush stdout
getLine >>= evaluate
Problem is, when I press the delete key (backspace on windows), instead of deleting a character from the buffer, I get a ^? character instead. What's the canonical way of getting delete to delete a character when reading from stdin? Similarly, I'd like to be able to get the arrow keys to move a cursor around, etc.

Compile the program and then run the compiled executable. This will give the correct behavior for the Delete key. For some reason interpreting the program screws up the use of Delete.
To compile the program, just invoke ghc like this:
$ ghc -O2 myProgram.hs
This will generate a myProgram executable that you can run from the command line:
$ ./myProgram
That will then give the correct behavior for Delete.

Related

How do I execute a list of commands in Haskell?

I'm new to Haskell and I have been using system to execute shell commands for me, since I'm only interested in exit status. I noticed that since I can do something like:
ls <- system "ls"
pwd <- system "pwd"
and this correctly executes the two commands. I was thinking about executing an array of these commands eg
lsAndPwd <- return $ system <$> ["ls", "pwd"]
and I'm surprised that this doesn't actually execute anything. This compiles and I checked that lsAndPwd has the correct type of [IO GHC.IO.Exception.ExitCode] but the commands are never executed. What's going on and how can I get this to work?
You should use mapM instead of <$> so you get an IO [ExitCode], not an [IO ExitCode]. This way, it's collected into one IO monad that you can run:
lsAndPwd <- mapM system ["ls", "pwd"]
Alternatively, call sequence on the whole thing:
lsAndPwd <- sequence $ system <$> ["ls", "pwd"]

Why doesn't my Haskell cmd line program get arguments from Vim Bang?

Vim has the possibility to let you replace selected text with the output of an external program. I'd like to take advantage of this with programs that I'd write in Haskell. But it doesn’t get the selected text as args.
-- show-input.hs
module Main where
import System.Environment
main = do
input <- getArgs
putStr ("Input was: " ++ (show input))
When I run it from the command line (NixOS GNU/Linux, BASH), I get the expected behavior:
$ ./show-input test
Input was: ["test"]
When I select some text in Vim and invoke :'<,'>!~/show-input, I get this :
Input was: []
There is something weird here, but I can't tell if it is from the way Vim passes arguments or from the way Haskell gets them. I have tried with both console Vim and graphical gVim (8.0.1451), with the same result.
NB: I can successfully use Vim Bang! with other external programs, such as grep. It works great.
---
Correct version after chepner's answer
So, for anyone interested, just replace getArgs with getContents and you get your input all in a string (instead of a list of strings).
module Main where
import System.Environment
main = do
input <- getContents
putStr ("Input was: " ++ (show input))
The ! command sends the seleted text to the program via standard input, not as a command line argument. The command line equivalent would be somecommand | ./show-input.

Weird buffering with prompt in haskell [duplicate]

This question already has answers here:
Why doesn't Haskell sequence these IO actions properly?
(2 answers)
Closed 7 years ago.
I was playing around in Haskell and noticed something weird. I've defined a simple prompt function below.
-- file: test.hs
main :: IO ()
main = putStrLn . ("Hello, " ++) =<< (putStr "Name: " >> getLine)
When I runhaskell this, it works as expected, printing the prompt, waits for my input, then prints the greeting.
$ runhaskell test.hs
Name: kwarrtz
Hello, kwarrtz
When I compile it, however, things get weird. When I run it, it doesn't print the prompt, instead giving me a blank line and waiting for input. When I type my name and hit enter, it prints the prompt and the greeting, on the same line. In otherwords, the getLine happens before the putStr.
$ ghc test.hs
$ ./test
kwarrtz
Name: Hello, kwarrtz
Any thoughts on what's happening? I imagine it has something to do with the line buffering on my terminal, but I'm not sure how (that or I've just made some really ridiculous mistake in my code).
I'm running GHC 7.8.3 on Mac OS X El Capitan and using the default Terminal app.
Buffering.
hSetBuffering stdout NoBuffering
I think you can get all that from System.IO

What's the right way to :reload and run :main as a single command in GHCi?

Is there a way to chain :reload/:r along with :main as a single command in GHCi?
The goal here is to avoid typing both every time I change something in my other terminal, but to just type ↑Enter.
:cmd seems to accept string with multiple lines.
Therefore you can do the following command.
:cmd return $ unlines [":reload",":main"]
also you can add following code to ~/.ghci
:def hoge const $ return $ unlines [":reload",":main"]
now you can execute :hoge in ghci

How do you compile and run haskell on notepad++

How do you compile and run Haskell on notepad++
I installed the plugin NppExec and then I pressed F6
I saved my Haskell file to C:\Users\Sam\Desktop\haskell files\new 3.hs
So on the command after I press F6 I tried typing in a few different things:
C:\Users\Sam\Desktop\haskell files\new 3.hs`
ghc.exe new 3.hs
haskell new
but I got these responses:
C:\Users\Sam\Desktop\haskell files\new 3.hs
CreateProcess() failed with error code 2:
The system cannot find the file specified.
ghc.exe new 3.hs
Process started >>>
target `new' is not a module name or a source file
<<< Process finished.
haskell new 3
CreateProcess() failed with error code 2:
The system cannot find the file specified.
================ READY ================
What is the correct way of compiling and executing at haskell file on notepad++?
You need to set NppExec to work in the current directory, so In Plugins, NppExec, tick Follow $(CURRENT_DIRECTORY).
Use the command ghc new3.hs when you press F6 (no spaces in filenames).
If you're using Haskell with stack, I found a lovely way to run things quickly using NppExec. It's a simpler process than it looks and once you do it, you're good to go:
Suppose you have a file like this in a file called yourFileName.hs:
main :: IO ()
main = putStrLn "Hello world!"
Press F6 to begin NppExec. (See Note 1 below.)
Paste the below into the window.
cd "$(FULL_CURRENT_PATH)"
stack ghci
// This is a comment you can delete. Note 2 below.
(See Note 3 below.)
Upon pressing the OK button, the Notepad++ console will run the Haskell interpreter.
Now, press F6 again. A warning menu will pop up.
Type this into the menu: :cmd return $ unlines [":l yourFileName", ":main"] and press ENTER. The file will execute. Pressing F6+ENTER will load and run the file again. When you open Notepad++ next time, this will still be there. Whenever you want to work with a new file, you will have to change yourFileName of course.
Explanation: :cmd return " . . . " allows you to execute a string as multiple ghci commands, separated by \n. unlines takes a list of strings and joins them with \n. If you don't know about $, you'll learn it soon as it's part of basic Haskell.
If you don't have a main function in your file, then instead use :cmd return $ unlines [":l yourFileName"].
Note 1: For convenience, I used the Settings > ShortCutMapper > Plugin Commands to change Execute from F6 to F1.
Note 2: If you run multiple languages in this way (like maybe Lisp?), then you can replace the // This is a comment... line with // :cmd return $ unlines [":l yourFileName", ":main"] just so you have it for later when you switch back to Haskell.
Note 3: Instead of pasting cd "$(FULL_CURRENT_PATH)" stack ghci into the NppExec window, a much simpler way to do all this is to paste stack runghc "$(FULL_CURRENT_PATH)" and nothing else needs to be done. However I found the console takes a lot longer to load and run the file in that case, so the method above is what I use.

Resources