[Haskell-cafe] named pipes interface

Serge D. Mechveliani mechvel at botik.ru
Fri Jan 13 19:43:26 CET 2012

I thank people for the notes.
People write that the example without  unsafePerformIO  is desirable.
So I present the improved question and improved, "pure" code.

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 the first string in the loop, 
and then it ends with an error.

Main.hs  is given below. Can you, please, fix the code?

Please, copy the response to  mechvel at botik.ru


mechvel at botik.ru

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

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

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

axiomIO :: String -> IO String
axiomIO str = do
              toA   <- toA_IO    
              fromA <- fromA_IO  
              hPutStr toA str 
              hFlush toA
              hGetLine fromA
---------------------------------------------- Example of usage --
main = do
       putStr "str1  -->  "
       str1' <- axiomIO str1
       putStr (str1' ++ "\n")
       putStr "str2  -->  "
       str2' <- axiomIO str2
       putStr (str2' ++ "\n")
       n       = 9
       str0    = "ABC"
       strings = [str0 ++ (show i) | i <- [1 .. n]]
       str1: str2: _ = 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.

And it processes only the first string:
 m> ./Main
 str1  -->  abc1
 str2  -->  Main: /home/mechvel/m/toA: 
            openFile: does not exist (No such device or address)

More information about the Haskell-Cafe mailing list