fork download
  1. {-# language DeriveFunctor #-}
  2.  
  3. import Control.Monad
  4.  
  5. data IOpure a
  6. = Return a
  7. | Output String (IOpure a)
  8. | Input (String -> IOpure a)
  9. deriving Functor
  10.  
  11. instance Applicative IOpure where
  12. pure = Return
  13. (<*>) = ap
  14.  
  15. instance Monad IOpure where
  16. Return x >>= f = f x
  17. Output s io >>= f = Output s (io >>= f)
  18. Input k >>= f = Input (\s -> k s >>= f)
  19.  
  20. class Monad m => Interaction m where
  21. getInput :: m String
  22. produceOutput :: String -> m ()
  23.  
  24. instance Interaction IOpure where
  25. getInput = Input Return
  26. produceOutput x = Output x (Return ())
  27.  
  28. echoingUser :: IOpure a -> a
  29. echoingUser = go "no output"
  30. where
  31. go _ (Return x) = x
  32. go _ (Output o io) = go o io
  33. go o (Input k) = go o (k o)
  34.  
  35. interactiveProgram :: Interaction m => m (String, String)
  36. interactiveProgram = do
  37. produceOutput "Jeff"
  38. name <- getInput
  39. produceOutput "Bob"
  40. name2 <- getInput
  41. return (name, name2)
  42.  
  43. main :: IO ()
  44. main = print (echoingUser interactiveProgram)
  45.  
Success #stdin #stdout 0s 4492KB
stdin
Standard input is empty
stdout
("Jeff","Bob")