Stopping a program from exiting after completion - windows

I'm new to Haskell and trying to set it up on a windows machine. I get it to compile but when I run the .exe file, the program runs and exits right away, barely showing the output.
Below is the sample code I created
module Main where
m = 2 * n
n = f 4
--functions
f::Int -> Int
f x = 2 * x
g::Int -> Int -> Int
g x y = 2 * x * y
main = do
x <-getChar --used to pause program
print m
print $ f m
print $ g m n
I used the getChar to pause the program until a key is pressed. I've been trying to figure out how to do something like exit on a key stroke after the print statements. How can I do this and could there be a better way?

If you run your program in Windows by clicking on it, then it gets a terminal window of its own which itself exits once the program does. I guess that's what you did, or similar.
But if you instead start a terminal window with a DOS prompt, and run the program from there, then that window will survive after the program ends and you can see your output.
You could also run the program from inside GHCi or WinGHCi with the :main command.
Lastly, your x <- getChar could almost work at the end of main, but there's a rule that the last statement in a do block must be an expression, so it cannot bind a variable. But you are not using x for anything, so you can just remove the x <- part:
main = do
print m
print $ f m
print $ g m n
getChar --used to pause program

Related

Haskell not executing all external shell commands

I wrote this program and I compiled with:
ghc --make shell.hs
When I run it looks like:
$./shell
enter your number:
6
6
okay... it execute 6 time...
If I remove the sleep 2 statement then it exits fast but outputs only 6.
I tried to follow the advice (which is what is in the code below) given at this answer of a similar question but it didn't work.
It seems very strange that it is not executing all the commands. How do I force it to execute all commands and in a strict order? the lazyness is a good feature but when it comes to IO it just sucks or I am not enough of an expert to understand it.
What I want to do is execute all commands from a list in a strict order and I don't want Haskell to "intelligently" remove some of the commands on my behalf (if I want to execute sleep for 2 seconds in the shell, I should be allowed to do so).
If waitForProcess has to be used to resolve this, then my problem is I don't know how to use it. I have tried google but failed to see a simple example of it.
Please note that I want a working code solution for the program code I have given below and there should be a reasonable guarantee that the program works as expected on bash running on a typical Linux (say, Debian 7) as the Python program given below it runs.
import System.Process
import System.Exit
main = do
putStrLn "enter your number:"
n <- getLine
main1 (readInt n)
putStrLn ("okay... it execute " ++ n ++" time...")
readInt:: String -> Int
readInt = read
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
Below is a Python program and it works as desired with proper sleep:
import os
for i in range(6):
os.system("echo " + str(i))
os.system("sleep 2")
How about writing more like the Python version using forM_:
import Control.Monad
main1 n = do
forM_ [n,n-1 .. 1] $ \n -> do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
return ()
The program is doing what you are telling him to do:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
Here we have n == 6 so the condition of the if is false and then return () is executed, which terminates main1 doing nothing.
Note that if you passed n == 0 the condition would be true and it would execute main1 (-1) which then stops. In any case main1 will not repeat the commands n times it will always either execute them once (if n /= 0) or twice (if n == 0).
You could fix this by doing:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n > 0 then main1 (n-1) else return ()
Or, equivalently:
import Control.Monad
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
when (n > 0) $ main1 (n-1)
The problem here is that you are using general recursion to repeat a given statement. But general recursion can do anything and so you can easily produce bugs (as in your case). To avoid this it's often useful to use some other function to build your code. For example:
main1 n = sequence_ $ map execute [1..n]
execute i = do
ExitSuccess <- system $ "echo" ++ show i
ExitSuccess <- system $ "sleep 2"
return ()
Or:
main1 n = mapM_ execute [1..n]
Here you know what mapM_ and [1..n] do and so combining them tells you that you the execute action will be executed n times.
In any case the IO monad guarantees the the actions are all executed and in order, so you should not attribute to Haskell lazyness the fact that the code wasn't executed the expected number of times.
The problem with lazyness and input/output are different.

Can a program decide whether an arbitrary program halts for SOME input?

Is there a program (may-halt? p) that can tell whether there exists an input so that (p input) halts?
I tried simple diagonalization, but it only tells me that (may-halt? diag-may-halt) must be true. It doesn't help proving whether the program exists or not.
Does such a program exist?
Nope, may-halt? doesn't exist.
(I don't think a direct proof by diagonalization would be less complex than the proof that the Halting problem is undecidable; otherwise that would be the standard example. Instead, let's reduce your problem to the Halting problem:)
Suppose there was a program may-halt? p, that decides if program p halts for some input. Then define:
halt? p x := may-halt? (\y -> if y==x then p x else ⊥)
where the thing in braces is a derived program. Lets break it down:
halt? p x := may-halt? p'
where p' is the program that (i) on input x computes p x, (ii) on any other input just loops around without terminating:
p' y := if y==x then p x else ⊥
Then may-halt? p' outputs true if and only if p x terminates.
Thus, for any program p and input x, halt? p x would decide if p x terminates. But we know that that isn't possible, so may-halt? doesn't exist.

is there a formula to get a term from nested loop?

I have a nested loop as follows :
xl = yl = [a for a in range(1,12)]
ll = [a for a in range(0,6)]
c = 0;
output = []
for x in xl:
for y in yl:
if (y > x):
for l in ll :
output.append("{0}-{1}-{2}".format(x,y,l));
c+=1;
Given a value of c which is the position of a certain term, I need to get the value of that term.
For example if c = 10, I need the 10th element of output.
it would be awesome if someone told could give me a generic formula for all nested loops.
I tried googling, but I don't even know what terms to google.
Well you have put the output into an array, so you can simply look at output[10].
As for the bigger problem that you are trying to solve, I believe that you want to learn about generators. Here is how you work with them. First you put your loop in a function, and call yield where you want and no return statement. Like so.
def loop_generator ():
xl = yl = [a for a in range(1,12)]
ll = [a for a in range(0,6)]
for x in xl:
for y in yl:
if (y > x):
for l in ll :
yield (x, y, 1)
Now x = loop_generator() will return a generator. This is an object that, every time you call next on it, will start running code in the function and will return the next point yield would be called. If you run out of yields it will raise the StopIteration exception.
So your code now can be finished off with:
my_generator = loop_generator()
# Throw away 9 values
for i in range(9):
next(my_generator)
# Get the one I want
x, y, l = next(my_generator)
# Show what I got.
print "{0}-{1}-{2}".format(x,y,l)
This strategy can be used to turn any nested loop into something that you can step through and pull values out of.
Incidentally Python's native looping constructs all know to call next and terminate cleanly on StopIteration so that the following works as you might hope:
for x, y, l in loop_generator():
print "{0}-{1}-{2}".format(x,y,l)

Batching actions for caching and performance while avoiding the dirty work

Say I have two pure but unsafe functions, that do the same, but one of them is working on batches, and is asymptotically faster:
f :: Int -> Result -- takes O(1) time
f = unsafePerformIO ...
g :: [Int] -> [Result] -- takes O(log n) time
g = unsafePerformIO ...
A naive implementation:
getUntil :: Int -> [Result]
getUntil 0 = f 0
getUntil n = f n : getUntil n-1
switch is the n value where g gets cheaper than f.
getUntil will in practice be called with ever increasing n, but it might not start at 0. So since the Haskell runtime can memoize getUntil, performance will be optimal if getUntil is called with an interval lower than switch. But once the interval gets larger, this implementation is slow.
In an imperative program, I guess I would make a TreeMap (which could quickly be checked for gaps) for caching all calls. On cache misses, it would get filled with the results of g, if the gap was greater than switch in length, and f otherwise, respectively.
How can this be optimized in Haskell?
I think I am just looking for:
an ordered map filled on-demand using a fill function that would fill all values up to the requested index using one function if the missing range is small, another if it is large
a get operation on the map which returns a list of all lower values up to the requested index. This would result in a function similar to getUntil above.
I'll elaborate in my proposal for using map, after some tests I just ran.
import System.IO
import System.IO.Unsafe
import Control.Concurrent
import Control.Monad
switch :: Int
switch = 1000
f :: Int -> Int
f x = unsafePerformIO $ do
threadDelay $ 500 * x
putStrLn $ "Calculated from scratch: f(" ++ show x ++ ")"
return $ 500*x
g :: Int -> Int
g x = unsafePerformIO $ do
threadDelay $ x*x `div` 2
putStrLn $ "Calculated from scratch: g(" ++ show x ++ ")"
return $ x*x `div` 2
cachedFG :: [Int]
cachedFG = map g [0 .. switch] ++ map f [switch+1 ..]
main :: IO ()
main = forever $ getLine >>= print . (cachedFG !!) . read
… where f, g and switch have the same meaning indicated in the question.
The above program can be compiled as is using GHC. When executed, positive integers can be entered, followed by a newline, and the application will print some value based on the number entered by the user plus some extra indication on what values are being calculated from scratch.
A short session with this program is:
User: 10000
Program: Calculated from scratch: f(10000)
Program: 5000000
User: 10001
Program: Calculated from scratch: f(10001)
Program: 5000500
User: 10000
Program: 5000000
^C
The program has to be killed/terminated manually.
Notice that the last value entered doesn't show a "calculated from scratch" message. This indicates that the program has the value cached/memoized somewhere. You can try executing this program yourself; but have into account that threadDelay's lag is proportional to the value entered.
The getUntil function then could be implemented using:
getUntil :: Int -> [Int]
getUntil n = take n cachedFG
or:
getUntil :: Int -> [Int]
getUntil = flip take cachedFG
If you don't know the value for switch, you can try evaluating f and g in parallel and use the fastest result, but that's another show.

Change output of pause command in batch script

I'm writing a Windows batch script. By default, the pause command will pause the script and display the text "Press any key to continue...".
How do I modify this text to display my own text to the user?
You could hide the text from the pause command by using this:
pause >nul
Then you could echo your own message to tell the user it has paused:
echo The batch file has paused
So the full script might look like this:
#echo off
echo Hello World!
echo The batch file has paused
pause >nul
Here's a one-liner
pause>nul|set/p =any key to exit ...
It's slightly shorter (one less 'nul')
than Aacini's solution:
set/p<nul =any key to exit ...&pause>nul
and, with the 'pause' first, I think that
it's a little clearer what the intent is.
With both
cursor stays on the same line
ANY key works, not just 'enter'
Neither are as good, however, as the hypothetical
pause/t any key to exit ...
It's hard to believe that 'pause' has survived
35 years without this ability ;-)
The solutions with 'echo' have the possibly undesirable
trailing new-line,
but do provide for multiple lines of text:
Pause>nul|(echo All your bases &echo are belong to us &echo Press any key to die...)
bv
"Not really what I was looking for, I was wondering whether there was a way of actually changing the output text of the Pause command, not just a workaround to it." – Hashim
Yes, you can! But you must be aware that PAUSE is an internal command of CMD.EXE program, so, to modify the message that PAUSE show, you must modify CMD.EXE file. To do that, you must use an editor that may modify binary files. I used XVI32 program via these steps:
1- Copy CMD.EXE file to a new folder created for this purpose: COPY %COMSPEC%
2- Edit the copy of CMD.EXE with XVI32.EXE program:
2.1- Locate the message you want. Messages are stored in 16-bits elements with the high byte equal zero. To locate a message:
2.1.1- In Search> Find> Text string> enter the message you want.
2.1.2- Convert Text -> Hex
2.1.3- Insert a zero after each letter-value
2.1.4- Press Ok
2.2- Modify the message for the new one. Modify existent letters only and keep zeros in place. Note that you can NOT extend any message.
2.3- End the edition and save the modified file.
You may now run CMD.EXE to get the modified PAUSE message. I made a test of this procedure:
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>pause
Press any key to continue . . .
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>cmd
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>pause
Oprime una tecla para seguir. .
Notes to everyone that read this answer:
NOTE 1: Please, don't post that comment saying that modifying CMD.EXE file must NEVER be done! I think the same. I just posted this answer so the OP realized what he really asked for...
NOTE 2: The reviewing of CMD.EXE file with a text editor, like Notepad, is very interesting. You may see all the internal commands, interesting details (like =ExitCode and =ExitCodeAscii variables), all the error messages, etc. For example, these are the internal commands:
C O L O R T I T L E C H D I R C L S C M D E X T V E R S I O N
D E F I N E D C O P Y P A T H P R O M P T P U S H D P O P D
A S S O C F T Y P E D A T E D E L D I R E C H O E N D L O C A L
E R A S E E R R O R L E V E L E X I T E X I S T B R E A K F O R
G O T O I F K E Y S M K D I R M D N O T P A U S E R D
R E M M O V E R E N A M E R E N R M D I R S E T S E T L O C A L
S H I F T S T A R T T I M E T Y P E V E R I F Y V E R V O L = , ; + / [ ] " : . \
P A T H E X T P A T H P R O M P T
F O R / ? I F / ? R E M / ?
% s % s
% s
/ A / P : E O F
f d p n x s a t z D O
/ L / D / F / R I N E L S E ( % s ) % s % s % s % s
% c % c % s % s & ( ) [ ] { } ^ = ; ! % ' + , ` ~
There is no way to change the text of the pause command. However you might want to look at the choice command. You can change the text it prints. The only downside is that you need to provide a list of acceptable characters.
Already many solutions. Another variation that makes some sense:
echo Hit any key to continue...&pause>nul
Another dirty solution would be something like this,
SET /P =Press enter to return to the menu . . .
GOTO :menu
The benefit of this is that the cursor stays on the same line as the message, just like with the PAUSE command.
The downside is that it only listens to the enter key.
Here’s another trick
Pause. >nul | echo. Press something to continue
Starting from Windows 2000 (so, not XP) you can use the choice command which is far more powerful than either pause or set /p.
Besides being able to specify your own prompt text, you can also require the user to type a specific key, and only that key, instead of being limited to, and requiring, [Enter] to be pressed.
Also, you can prompt the user to press a number of different keys and take action based on which key was pressed.
Type choice /? for help, or read more about it here: Wikipedia: choice (command)
You could do it like this!
#echo off
echo Hello World!
echo:
echo Press 1 to continue
set /p letter=
if %letter% == 1 goto a ;or instead of goto you could write start and the file or website you want to start
pause >nul
:a
cls
echo BYE NOW!
pause >nul
pause|echo text you want displayed
Since I dont see it suggested and every dog on the internet has had a go, but me.
This may not have worked under XP, as required by OP, but is valid for any newer system like my current Win7 :-)
Dirty version (no message) |keys ON does nothing, but block the press any key ...
timeout -1|Keys ON
can be used for message after
#timeout -1|Keys ON&echo I'm back
This one will pause and show a response until accepted then return to prompt/next cmd line
#timeout -1|Echo Hello Padawan %userprofile:~9%, Press a key, you can!
:on any keys
#echo Welcome to the dark side

Resources