[Haskell-cafe] unsafePerformIO usage
Serge D. Mechveliani
mechvel at botik.ru
Sun May 6 22:21:15 CEST 2012
People,
can anybody explain what incorrect may happen with the following
program which uses exchange through two Unix pipes and
unsafePerformIO ?
The pipes are created by the Unix commands
mkfifo toA; mkfifo fromA
gcc iface.c compiles the C program to a.out.
ghc --make Main compiles the Haskell program by GHC to ./Main
Run on the second terminal > ./iface
Run on the first terminal > ./Main
It prints the result to the screen.
In Main.hs, the function iface :: String -> String
is defined via hPutStr, hGetLine, hFlush, unsafePerformIO. It
outputs str :: String to the pipe toA;
the process iface (programmed in C) waits for delay and returns
the respond string through the pipe fromA;
iface inputs this respond string.
So far, I put the respond string to be the same string,
I think, this is not essential, but another map can be considered.
Assume that the parallel computation is not allowed.
In the below `main', I tried
f ss where
ss = [iface $ shows i "\n" | i <- [1 .. 4]],
f [s1, s2, s3, s4] = [s3++s1, s3++s2, s1++s2],
and it works correct.
The question is:
what a simple definition is possible for f which will evaluate
incorrect?
Is this true that unsafePerformIO is _safe_ for all f in this
context?
The `delay' constant can be edited in fifo.c.
See both sources below.
Please, copy the respond to mechvel at botik.ru
Thanks,
------
Sergei
mechvel at botik.ru
------------------------------------------------------------------------
import System.IO (IOMode(..), IO(..), Handle, openFile, hPutStr,
hGetLine, hFlush)
import System.IO.Unsafe (unsafePerformIO)
dir = showString "/home/mechvel/haxiom/unsafeTest/"
-- openFile :: FilePath -> IOMode -> IO Handle
-- hPutStr :: Handle -> String -> IO ()
-- hGetLine :: Handle -> IO String
toA_IO = openFile (dir "toA") WriteMode :: IO Handle
fromA_IO = openFile (dir "fromA") ReadMode
toA = unsafePerformIO toA_IO
fromA = unsafePerformIO fromA_IO
initIO :: IO (Handle, Handle)
initIO = do
to <- toA_IO
from <- fromA_IO
return (to, from)
ifaceIO :: (Handle, Handle) -> String -> IO String
ifaceIO (h1, h2) str = do
hPutStr h1 str
hFlush h1
str' <- hGetLine h2
return str'
iface :: String -> String
iface str = unsafePerformIO $ ifaceIO (toA, fromA) str
main = putStr $ shows [s3++s1, s3++s2, s1++s2] "\n"
where
ss@[s1, s2, s3, s4] = [iface $ shows i "\n" | i <- [1 .. 4]]
-- The C program fifo.c ---------------------------------------------
#include <stdio.h>
#include <string.h>
#define BOUND 64
static char str[BOUND];
main()
{
int l, i; long j; FILE *toA, *fromA;
toA = fopen("/home/mechvel/haxiom/unsafeTest/toA", "r");
if (toA == NULL) {perror("fopen(toA, r) failed: "); return;};
fromA = fopen("/home/mechvel/haxiom/unsafeTest/fromA", "w");
if (fromA == NULL) {perror("fopen(fromA, w) failed: "); return;};
for (;;)
{
if (fgets(str, BOUND, toA) == NULL) {
perror("fgets(str, bound, toA) failed: "); return;
};
j = 20000000; // delay. edit it
while (j > 0) {j = j-1;};
fputs(str, fromA);
fflush(fromA);
};
return;
}
More information about the Haskell-Cafe
mailing list