[Haskell-cafe] named pipe interface

Serge D. Mechveliani mechvel at botik.ru
Thu Jan 12 19:53:48 CET 2012


(I wonder: is this for  beginners at haskell.org ?)

I need to organize a  string interface  for a Haskell function  
Main.axiom  and a C program   

via a pair of  named pipes  (in Linux, UNIX).
The pipes are created before running, by the commands   > mkfifo toA
                                                        > mkfifo fromA
Main.axiom  outputs a  string  to  toA  and inputs the respond string 
                                            from  fromA  as the result.
fifoFromA  inputs a string from  toA, 
           converts it to the string  resStr,  outputs resStr to  fromA.

Main.axiom  must be able to be applied in a loop,
and there must be avoided repeated opening of a file/channel in a loop.
As an example, the string conversion in  fifoFromA.c  is put the 
conversion of each character to the lower case:

-------------------------- fifoFromA.c  ------------------------------
#include <string.h>
#include <stdio.h>
#include <fcntl.h>

#define BOUND 64

int main()
  int  toA, fromA, i, numread;
  char buf[BOUND];

  toA = open("toA", O_RDONLY);  fromA = open("fromA", O_WRONLY);

  for (;;)
    numread = read(toA, buf, BOUND);
    buf[numread] = '\0';
    // printf("A:  Read from toA:  %s\n", buf);

    i = 0;                     // convert the string to the lower case
    while (i < numread) {buf[i] = tolower(buf[i]);  i++;}
    write(fromA, buf, strlen(buf));

For the "to-A" part writen in C  (instead of Haskell), this interface 
loop works all right.
With Haskell, I manage to process only a single string in the loop, 
and then it ends with an error.

Main.hs  is given below.

I never dealt with such an IO in Haskell.
Can you, please, fix the code or give comments?

Please, copy the response to  mechvel at botik.ru
(I am not in the list).

Thank you in advance for your notes,

mechvel at botik.ru

import System.IO (IOMode(..), IO(..), Handle, openFile, hPutStr, 
                                              hGetLine, hFlush)
import System.IO.Unsafe (unsafePerformIO)

dir = showString "/home/mechvel/ghc/axiomInterface/byLowerLevel/"

toA_IO   = openFile (dir "toA")   WriteMode    :: IO Handle
fromA_IO = openFile (dir "fromA") ReadMode  
                                           -- used as global values
toA   = unsafePerformIO toA_IO             -- 
fromA = unsafePerformIO fromA_IO           --

axiomIO :: String -> IO String
axiomIO str = do
              hPutStr toA str 
              hFlush toA
              hGetLine fromA

axiom :: String -> String -> String
axiom str =  showString (unsafePerformIO $ axiomIO str)

-- Examples of usage --------------------------------------------
main = putStr (axiom "ABC1" "\n")    -- I

 -- putStr (axiom "ABC1" $ showChar '\n' $ axiom "ABC2" "\n")   -- II

 {- III:
    putStr (shows resPairs "\n")
       n        = 9000
       str0     = "ABC"
       strings  = [str0 ++ (show i) | i <- [1 .. n]]
       resPairs = [(str, axiom str "") | str <- strings]

I use  Glasgow Haskell  ghc-7.01.

Build:    > gcc -o fifoFromA fifoFromA.c
          > ghc --make Main

Running:  first, command     > ./fifoFromA
          on  terminal-2,
          then command       > ./Main
          on  terminal-1.

Now, the example  (I)  works  
-- in the sense that terminal-1 shows the result  "abc1"  
after the program on  terminal-2  is interrupted.

II and III do not work. And the aim is the examples like III.

More information about the Haskell-Cafe mailing list