```{- |
Description: IO monad without do notation
Maintainer: dev@chungyc.org

Part of Ninety-Nine Haskell "Problems".  Some solutions are in "Solutions.P74".
-}
module Problems.P74
-- * Original function
-- | The function below is the equivalent implementation of 'askGoldbach' using do notation.
-- * Supporting function
-- | The function below is not part of the problem.
-- This is for use in examples and tests.
, withFixedInput) where

import           Solutions.P40  (goldbach)
import qualified Solutions.P74  as Solution
import           System.IO
import           System.Process (createPipe)

-- \$setup
-- >>> import System.IO

{- |
We would like to implement a function which reads an even number from standard input,
finds two prime numbers which add up to the number (see 'Problems.P40.goldbach'),
and prints out the equation to standard output.

Given the use of input and ouput, this could be written with the IO monad in do notation:

@
askGoldbach :: Handle -> Handle -> IO ()
s <- hGetLine hIn
let n = read s :: Int
let (a,b) = goldbach n
hPutStr hOut \$ show n
hPutStr hOut "="
hPutStr hOut \$ show a
hPutStr hOut "+"
hPrint hOut b
@

Implement the function without do notation.
In other words, use '>>=' or '>>' directly, instead of using them implicitly through do notation.
Try to use these functions with prefix style instead of infix style.

=== Examples

104=3+101

=== __Hint__

In do notation,

> do
>   a
>   b

is a shorthand for

> (>>) a b

or equivalently,

> (>>=) a (\_ -> b)

Also,

> do
>   x <- a
>   b

is a shorthand for

> (>>=) a (\x -> b)

For those not familiar with monads, using these functions directly in prefix style
will make it more apparent that these are not just sequenced statements as
in imperative languages, but really a series of function applications.
The distinction may be minor in the context of IO monads,
but it will make it easier to understand other kinds of monads such as 'Maybe'.

While not relevant to this problem, also note that 'return' is /not/
a return statement as in most languages,
but a function that injects a value into the monad.  For example,

> f = do
>   (a,b) <- return (1,2)
>   return (a+1,b+1)

The naming of 'return' can make the function body similar
to what one would expect from imperative languages.  For example,

> f :: IO String
> f = do
>   s <- getLine
>   return \$ "Got string: " ++ s

But one should be careful to remember that it is not a return statement as such.
-}
askGoldbach :: Handle -> Handle -> IO ()
askGoldbach :: Handle -> Handle -> IO ()
askGoldbach = Handle -> Handle -> IO ()

{- |
Reads an even number from standard input,
finds two prime numbers which add up to the number,
and prints out the equation to standard output.

This is an implementation of 'askGoldbach' in do notation.

=== Examples

104=3+101
-}
askGoldbach' :: Handle -> Handle -> IO ()
askGoldbach' :: Handle -> Handle -> IO ()
hIn Handle
hOut = do
String
s <- Handle -> IO String
hGetLine Handle
hIn
let n :: Int
n = forall a. Read a => String -> a
s :: Int
let (Int
a,Int
b) = forall a. Integral a => a -> (a, a)
goldbach Int
n
Handle -> String -> IO ()
hPutStr Handle
hOut forall a b. (a -> b) -> a -> b
\$ forall a. Show a => a -> String
show Int
n
Handle -> String -> IO ()
hPutStr Handle
hOut String
"="
Handle -> String -> IO ()
hPutStr Handle
hOut forall a b. (a -> b) -> a -> b
\$ forall a. Show a => a -> String
show Int
a
Handle -> String -> IO ()
hPutStr Handle
hOut String
"+"
forall a. Show a => Handle -> a -> IO ()
hPrint Handle
hOut Int
b

{- |
Given a string and an output handle,
apply the function to a constructed input handle and the given output handle.
The input handle will read the given string.

=== Examples

>>> withFixedInput "This is the input." stdout (\i -> \o -> hGetLine i >>= hPutStrLn o)
This is the input.
-}
withFixedInput :: String -> Handle -> (Handle -> Handle -> IO ()) -> IO ()
withFixedInput :: String -> Handle -> (Handle -> Handle -> IO ()) -> IO ()
withFixedInput String
s Handle
hOut Handle -> Handle -> IO ()
f = do
(Handle
writeEnd) <- IO (Handle, Handle)
createPipe
Handle -> String -> IO ()
hPutStrLn Handle
writeEnd String
s
Handle -> IO ()
hClose Handle
writeEnd
Handle -> Handle -> IO ()
f Handle