[Haskell-beginners] Mixing IO and other monads
Henk-Jan van Tuyl
hjgtuyl at chello.nl
Mon Aug 30 07:50:31 EDT 2010
On Mon, 30 Aug 2010 00:56:06 +0200, Brian Victor <homeusenet4 at brianhv.org>
wrote:
> main :: IO ()
> main = do
> initialize
> ideviceId <- getDefaultInputDeviceID
> case ideviceId of
> Nothing -> putStrLn "No default input device"
> Just inputDeviceId -> do
> odeviceId <- getDefaultOutputDeviceID
> case odeviceId of
> Nothing -> putStrLn "No default output device"
> Just outputDeviceId -> do
> openInputResult <- openInput inputDeviceId
> case openInputResult of
> Right err -> putStrLn $ show err
> Left inputStream -> do
> openOutputResult <- openOutput
> outputDeviceId 0
> case openOutputResult of
> Right err -> putStrLn $ show err
> Left outputStream -> runTranslationLoop
> inputStream outputStream
>
>
This can be made more readable if main is split up:
> main :: IO ()
> main = do
> initialize
> ideviceId <- getDefaultInputDeviceID
> case ideviceId of
> Nothing -> putStrLn "No default input device"
> Just inputDeviceId -> main2 inputDeviceId
> where
> main2 inputDeviceId = do
> odeviceId <- getDefaultOutputDeviceID
> case odeviceId of
> Nothing -> putStrLn "No default output device"
> Just outputDeviceId -> main3 inputDeviceId outputDeviceId
>
> main3 inputDeviceId outputDeviceId =
> do
> openInputResult <- openInput inputDeviceId
> case openInputResult of
> Right err -> putStrLn $ show err
> Left inputStream -> main4 inputDeviceId outputDeviceId
> inputStream
>
> main4 inputDeviceId outputDeviceId inputStream =
> do
> openOutputResult <- openOutput outputDeviceId 0
> case openOutputResult of
> Right err -> putStrLn $ show err
> Left outputStream -> runTranslationLoop inputStream
> outputStream
This can be made more compact with the aid of the following two functions:
> ifLeft x f =
> x' <- x
> case x' of
> Right err -> putStrLn $ show err
> Left y -> f y
> ifJust x f msg =
> x' <- x
> case x' of
> Nothing -> putStrLn msg
> Just y -> f y
The main program than becomes:
> main :: IO ()
> main = do
> initialize
> ifJust getDefaultInputDeviceID
> main2 "No default input device"
>
> where
> main2 inputDeviceId = ifJust getDefaultOutputDeviceID
> (main3 inputDeviceId) "No default output device"
>
> main3 inputDeviceId outputDeviceId =
> ifLeft (openInput inputDeviceId)
> (main4 inputDeviceId outputDeviceId)
>
> main4 inputDeviceId outputDeviceId inputStream =
> ifLeft (openOutput outputDeviceId 0)
> (runTranslationLoop inputStream)
Of course, another thing to prevent long lines, is to use two spaces for
indentation.
Met vriendelijke groet,
Henk-Jan van Tuyl
--
http://Van.Tuyl.eu/
http://members.chello.nl/hjgtuyl/tourdemonad.html
--
More information about the Beginners
mailing list