module System.IO.Lazy.Applicative where

import qualified Data.ApplicativeChain as Chain
import Control.Applicative (Applicative(pure, (<*>)), )
import Control.Monad (liftM2, )
import System.IO.Unsafe (unsafeInterleaveIO, )


newtype T a = Cons {decons :: IO (Chain.T a)}

data RunAll = RunAll
   deriving Show

instance Functor T where
   fmap f = Cons . fmap (fmap f) . decons

instance Applicative T where
   pure = Cons . return . Chain.Cons Chain.RunAll
   Cons f <*> Cons x = Cons $ liftM2 (<*>) f x

-- instance MonadIO T where
liftIO :: IO a -> T a
liftIO = Cons . unsafeInterleaveIO . fmap (Chain.Cons Chain.RunAll)

run :: T a -> IO a
run = fmap Chain.result . decons

{-
run $ liftA (\ ~( ~(a,b), ~(c,d)) -> a) $ liftA2 (,) (liftA2 (,) (liftIO getLine) (liftIO getLine)) (liftA2 (,) (liftIO getLine) (liftIO getLine))
-}