{-| 'String'-based 'IO' operations. Note that 'String's are very inefficient, and I will release future separate packages with 'ByteString' and 'Text' operations. I only provide these to allow users to test simple I/O without requiring additional library dependencies. -} module Control.Proxy.Prelude.IO ( -- * Standard I/O -- ** Input getLineS, getLineC, readLnS, readLnC, -- ** Output printB, printD, printU, putStrLnB, putStrLnD, putStrLnU, -- ** Interaction promptS, promptC, -- * Handle I/O -- ** Input hGetLineD, hGetLineU, -- ** Output hPrintB, hPrintD, hPrintU, hPutStrLnB, hPutStrLnD, hPutStrLnU ) where import Control.Monad (forever) import Control.Monad.Trans.Class (lift) import Control.Proxy.Prelude.Kleisli (foreverK) import Control.Proxy.Core (Proxy, Client, Server) import Control.Proxy.Class (request, respond) import System.IO (Handle, hGetLine, hPutStr, hPutStrLn, hPrint, stdin, stdout) -- | Get input from 'stdin' one line at a time and send \'@D@\'ownstream getLineS :: y' -> Proxy x' x y' String IO r getLineS _ = forever $ do str <- lift getLine respond str -- | Get input from 'stdin' one line at a time and send \'@U@\'pstream getLineC :: y' -> Proxy String x y' y IO r getLineC _ = forever $ do str <- lift getLine request str -- | 'read' input from 'stdin' one line at a time and send \'@D@\'ownstream readLnS :: (Read a) => y' -> Proxy x' x y' a IO r readLnS _ = forever $ do a <- lift readLn respond a -- | 'read' input from 'stdin' one line at a time and send \'@U@\'pstream readLnC :: (Read a) => y' -> Proxy a x y' y IO r readLnC _ = forever $ do a <- lift readLn request a {-| 'print's all values flowing through it to 'stdout' Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -} printB :: (Show a, Show a') => a' -> Proxy a' a a' a IO r printB = foreverK $ \a' -> do lift $ do putStr "U: " print a' a <- request a' lift $ do putStr "D: " print a respond a -- | 'print's all values flowing \'@D@\'ownstream to 'stdout' printD :: (Show a) => x -> Proxy x a x a IO r printD = foreverK $ \x -> do a <- request x lift $ print a respond a -- | 'print's all values flowing \'@U@\'pstream to 'stdout' printU :: (Show a') => a' -> Proxy a' x a' x IO r printU = foreverK $ \a' -> do lift $ print a' x <- request a' respond x {-| 'putStrLn's all values flowing through it to 'stdout' Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -} putStrLnB :: String -> Proxy String String String String IO r putStrLnB = foreverK $ \a' -> do lift $ do putStr "U: " putStrLn a' a <- request a' lift $ do putStr "D: " putStrLn a respond a -- | 'putStrLn's all values flowing \'@D@\'ownstream to 'stdout' putStrLnD :: x -> Proxy x String x String IO r putStrLnD = foreverK $ \x -> do a <- request x lift $ putStrLn a respond a -- | 'putStrLn's all values flowing \'@U@\'pstream to 'stdout' putStrLnU :: String -> Proxy String x String x IO r putStrLnU = foreverK $ \a' -> do lift $ putStrLn a' x <- request a' respond x -- | Convert 'stdin'/'stdout' into a line-based 'Server' promptS :: String -> Proxy x' x String String IO r promptS = foreverK $ \send -> do recv <- lift $ do putStrLn send getLine respond recv -- | Convert 'stdin'/'stdout' into a line-based 'Client' promptC :: y' -> Proxy String String y' y IO r promptC _ = forever $ do send <- lift getLine recv <- request send lift $ putStrLn recv -- | Get input from a handle one line at a time and send \'@D@\'ownstream hGetLineD :: Handle -> y' -> Proxy x' x y' String IO r hGetLineD h _ = forever $ do str <- lift $ hGetLine h respond str -- | Get input from a handle one line at a time and send \'@U@\'pstream hGetLineU :: Handle -> y' -> Proxy String x y' y IO r hGetLineU h _ = forever $ do str <- lift $ hGetLine h request str {-| 'print's all values flowing through it to a 'Handle' Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -} hPrintB :: (Show a, Show a') => Handle -> a' -> Proxy a' a a' a IO r hPrintB h = foreverK $ \a' -> do lift $ do hPutStr h "U: " hPrint h a' a <- request a' lift $ do hPutStr h "D: " hPrint h a respond a -- | 'print's all values flowing \'@D@\'ownstream to a 'Handle' hPrintD :: (Show a) => Handle -> x -> Proxy x a x a IO r hPrintD h = foreverK $ \x -> do a <- request x lift $ hPrint h a respond a -- | 'print's all values flowing \'@U@\'pstream to a 'Handle' hPrintU :: (Show a') => Handle -> a' -> Proxy a' x a' x IO r hPrintU h = foreverK $ \a' -> do lift $ hPrint h a' x <- request a' respond x {-| 'putStrLn's all values flowing through it to a 'Handle' Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -} hPutStrLnB :: Handle -> String -> Proxy String String String String IO r hPutStrLnB h = foreverK $ \a' -> do lift $ do hPutStr h "U: " hPutStrLn h a' a <- request a' lift $ do hPutStr h "D: " hPutStrLn h a respond a -- | 'putStrLn's all values flowing \'@D@\'ownstream to a 'Handle' hPutStrLnD :: Handle -> x -> Proxy x String x String IO r hPutStrLnD h = foreverK $ \x -> do a <- request x lift $ hPutStrLn h a respond a -- | 'putStrLn's all values flowing \'@U@\'pstream to a 'Handle' hPutStrLnU :: Handle -> String -> Proxy String x String x IO r hPutStrLnU h = foreverK $ \a' -> do lift $ hPutStrLn h a' x <- request a' respond x