In article <20050523.111714.74728525.ikegami / madscientist.jp>,
  Daisuke IKEGAMI <ikegami / madscientist.jp> writes:

> stdin を "NoBuffering" mode にすれば解決すると思います。
>
>> main = copyFile stdin stdout
>
> 
>
>   main = hSetBuffering stdin NoBuffering >> 
>            copyFile stdin stdout
>
> にして試してみてください。

そうすると、たしかに出力されるようになりました。

> デフォルトのバッファリングモードは Haskell 98 では規定されていないので、
> ハンドルを取り扱うときには、たとえ stdin であっても、hSetBuffering を
> 明示的に書くほうが無難です。
>
>  : 参照 : Haskell 98 report 11.4.2
>    The default buffering mode when a handle is opened is implementation-
>    dependent and may depend on the file system object which is attached
>    to the handle.

なるほど。調べてみると、ghc のデフォルトは BlockBuffering Nothing のようです。

ただ、runhugs のデフォルトのバッファリングモードは
BlockBuffering (Just 8192) なのですが、これは問題なく動きます。

% cat tst.hs
module Main where

import IO

main = hGetBuffering stdin >>= \mode ->
       hPutStrLn stdout (show mode) >>
       copyFile stdin stdout

copyFile h1 h2 = do
                   eof <- hIsEOF h1
                   if eof then return () else
                      do
                        c <- hGetChar h1
                        hPutChar h2 c
                        hFlush h2
                        copyFile h1 h2

% ruby -e 'STDOUT.sync=true; loop { sleep 1; print "a" }'| runhugs tst.hs
BlockBuffering (Just 8192)
aaaaa...

そこで、ghc でも BlockBuffering (Just 8192) にしてみたのですが、出力が
出てきません。

% cat tst.hs 
module Main where

import IO

main = hSetBuffering stdin (BlockBuffering (Just 8192)) >>
       hGetBuffering stdin >>= \mode ->
       hPutStrLn stdout (show mode) >>
       copyFile stdin stdout

copyFile h1 h2 = do
                   eof <- hIsEOF h1
                   if eof then return () else
                      do
                        c <- hGetChar h1
                        hPutChar h2 c
                        hFlush h2
                        copyFile h1 h2

% ghc tst.hs
% ruby -e 'STDOUT.sync=true; loop { sleep 1; print "a" }'| ./a.out                  
BlockBuffering (Just 8192)
(出力が出てこない)

ghc においてバッファリングモードが hIsEOF の挙動に影響するのはわかった
のですが、runhugs と違うのはなんででしょう?

デフォルトのバッファリングモード以外に実装依存な規定があるのでしょうか?
-- 
[田中 哲][たなか あきら][Tanaka Akira]

--
ML: haskell-jp / quickml.com
使い方: http://QuickML.com/