
Hi Haskell Cafe, I've defined the following reverse echo server that echos text back in reverse: module Programs.TcpEchoIterServer where import Control.Concurrent import Control.Exception import Control.Monad import Control.Monad.Trans import Data.IterIO import Data.IterIO.Inum import Network import System.IO import System.IO.Error (isEOFError) import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy.Char8 as C iterHandle' :: (MonadIO m) => Handle -> IO (Iter L.ByteString m (), Onum L.ByteString m a) iterHandle' = iterHandle main = withSocketsDo $ do sListen <- listenOn (PortNumber 8000) putStrLn "Listening on Port 8000" forkIO $ forever $ do (sSession, hostname, port) <- accept sListen hSetBuffering sSession NoBuffering putStrLn ("Connected to " ++ hostname ++ ":" ++ show port) forkIO $ do (iter, enum) <- iterHandle' sSession enum |$ inumLines .| inumReverse .| inumUnlines .| iter putStrLn "Press <CTRL-D> to quit." exitOnCtrlD iterLines :: (Monad m) => Iter L.ByteString m [L.ByteString] iterLines = do line <- lineI return [line] iterUnlines :: (Monad m) => Iter [L.ByteString] m L.ByteString iterUnlines = (L.concat . (++ [C.pack "\n"])) `liftM` dataI iterReverse :: (Monad m) => Iter [L.ByteString] m [L.ByteString] iterReverse = do lines <- dataI return (map L.reverse lines) inumLines = mkInum iterLines inumUnlines = mkInum iterUnlines inumReverse = mkInum iterReverse exitOnCtrlD = try getLine >>= either (\e -> unless (isEOFError e) $ ioError e) (const exitOnCtrlD) It all works fine. My question is: Is it possible to rewrite inumReverse to be this: iterReverse :: (Monad m) => Iter L.ByteString m L.ByteString iterReverse = do line <- dataI return (L.reverse line) inumReverse = mkInum iterReverse And still be able to use it in the line: enum |$ inumLines .| {-- inumReverse goes in here somehow --} .| inumUnlines .| iter The reason I ask is that the Haskell function reverse has the type [a] -> [a], not [[a]] -> [[a]]. I thought perhaps the alternative inumReverse is cleaner than the original as it behaves more similarly to Haskell's own reverse function. Cheers, -John

At Mon, 4 Jul 2011 20:36:33 +1000, John Ky wrote:
Hi Haskell Cafe,
enum |$ inumLines .| inumReverse .| inumUnlines .| iter ...
iterLines :: (Monad m) => Iter L.ByteString m [L.ByteString] iterLines = do line <- lineI return [line]
iterUnlines :: (Monad m) => Iter [L.ByteString] m L.ByteString iterUnlines = (L.concat . (++ [C.pack "\n"])) `liftM` dataI
iterReverse :: (Monad m) => Iter [L.ByteString] m [L.ByteString] iterReverse = do lines <- dataI return (map L.reverse lines)
inumLines = mkInum iterLines inumUnlines = mkInum iterUnlines inumReverse = mkInum iterReverse
It all works fine.
My question is: Is it possible to rewrite inumReverse to be this:
iterReverse :: (Monad m) => Iter L.ByteString m L.ByteString iterReverse = do line <- dataI return (L.reverse line)
inumReverse = mkInum iterReverse
And still be able to use it in the line:
enum |$ inumLines .| {-- inumReverse goes in here somehow --} .| inumUnlines .| iter
The reason I ask is that the Haskell function reverse has the type [a] -> [a], not [[a]] -> [[a]].
I thought perhaps the alternative inumReverse is cleaner than the original as it behaves more similarly to Haskell's own reverse function.
I'm not sure what you are trying to achieve. If you want an iter that works on L.ByteStrings, then you can say: iterReverse :: (Monad m) => Iter L.ByteString m L.ByteString iterReverse = do line <- lineI return (L.reverse line) In that case you don't need inumLines and inumUnlines. If, however, you want the type to be [L.ByteString], and you would rather do this one line at a time, instead of calling map, then you could do something like the following: iterReverse :: (Monad m) => Iter [L.ByteString] m [L.ByteString] iterReverse = do line <- headI return [L.reverse line] But the code you have above should also work, so it all depends on what you are trying to achieve. David
participants (2)
-
dm-list-haskell-cafe@scs.stanford.edu
-
John Ky