content: {-# LANGUAGE Arrows #-}
  
  module Main (
    module Main,
    module X,
  ) where
  
  -- base
  import Control.Arrow
  import Control.Concurrent
  
  -- transformers
  import Control.Monad.Trans.Class
  
  -- essence-of-live-coding
  import LiveCoding
  import LiveCoding.GHCi as X
  
  -- | An identity function that takes a long time to pass on its value.
  slowId :: Cell IO a a
  slowId = proc a -> do
    arrM threadDelay -< 1000000
    returnA -< a
  
  main :: IO ()
  main = do
    putStrLn "Push return to start a slow calculation."
    runHandlingStateT $ foreground $ liveCell mainCell
  
  {- | Constantly count the number of ticks passed since program start.
     Whenever the keyboard return key is pressed,
     this number is printed, and passed into a slow "computation" in a separate thread,
     while the foreground thread is not blocked.
     When the background thread returns, the number is printed again.
  -}
  mainCell :: Cell (HandlingStateT IO) () ()
  mainCell =
    let keyboard = nonBlocking False $ constM getLine -- Only poll, never abort
        mySlowId = nonBlocking True slowId -- Abort and restart when new data arrives
     in proc _ -> do
          n <- count -< ()
          lineMaybe <- keyboard -< Just ()
          let nString = show n <$ lineMaybe
          resampleMaybe (arrM $ lift . putStrLn) -< ("Calculating " ++) <$> nString
          resultMaybe <- mySlowId -< nString
          resampleMaybe (arrM $ lift . putStrLn) -< ("Calculated " ++) <$> resultMaybe
          arrM $ lift . threadDelay -< 1000 -- Don't hog CPU
  