module Control.Applicative.LazyIO 
  ( LazyIO 
  , liftLazyIO
  , runLazyIO 
  ) where

import System.IO.Unsafe (unsafeInterleaveIO) 

-- | Internals guarantee work does not repeat across threads (unsafeInterleaveIO) 
newtype LazyIO a = LazyIO { forall a. LazyIO a -> IO a
unLazyIO :: IO a } 

instance Functor LazyIO where
  fmap :: forall a b. (a -> b) -> LazyIO a -> LazyIO b
fmap a -> b
f LazyIO a
io = forall a. IO a -> LazyIO a
LazyIO forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (forall a. IO a -> IO a
unsafeInterleaveIO forall a b. (a -> b) -> a -> b
$ forall a. LazyIO a -> IO a
unLazyIO LazyIO a
io) 

instance Applicative LazyIO where
  pure :: forall a. a -> LazyIO a
pure = forall a. IO a -> LazyIO a
LazyIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure 
  LazyIO (a -> b)
f <*> :: forall a b. LazyIO (a -> b) -> LazyIO a -> LazyIO b
<*> LazyIO a
g = forall a. IO a -> LazyIO a
LazyIO forall a b. (a -> b) -> a -> b
$ do
    a -> b
f' <- forall a. IO a -> IO a
unsafeInterleaveIO forall a b. (a -> b) -> a -> b
$ forall a. LazyIO a -> IO a
unLazyIO LazyIO (a -> b)
f 
    a
g' <- forall a. IO a -> IO a
unsafeInterleaveIO forall a b. (a -> b) -> a -> b
$ forall a. LazyIO a -> IO a
unLazyIO LazyIO a
g 
    forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ a -> b
f' a
g'  
  

-- | IO action should be commutative (order independent) 
liftLazyIO :: IO a -> LazyIO a 
liftLazyIO :: forall a. IO a -> LazyIO a
liftLazyIO = forall a. IO a -> LazyIO a
LazyIO 

runLazyIO :: LazyIO a -> IO a 
runLazyIO :: forall a. LazyIO a -> IO a
runLazyIO = forall a. IO a -> IO a
unsafeInterleaveIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. LazyIO a -> IO a
unLazyIO