    {-# LANGUAGE CPP          #-}
    {-# LANGUAGE TypeFamilies #-}
    module Data.IOData where

    import           Control.Monad                 (liftM)
    import           Control.Monad.IO.Class
    import qualified Data.ByteString               as ByteString
    import qualified Data.ByteString.Char8         as ByteString8
    import qualified Data.ByteString.Lazy          as LByteString
    import           Data.ByteString.Lazy.Internal (defaultChunkSize)
    import qualified Data.Text                     as Text
    import qualified Data.Text.IO                  as Text
    import qualified Data.Text.Lazy                as LText
    import qualified Data.Text.Lazy.IO             as LText
    import           Prelude                       (Char, flip, ($), (.), FilePath)
    import qualified Prelude
    import           System.IO                     (Handle)
    import qualified System.IO

    #if !MIN_VERSION_text(0, 11, 3)
    import           Control.Exception             (handle, throwIO)
    import           System.IO.Error               (isEOFError)
    #endif

    -- | Data which can be read to and from files and handles.
    --
    -- Note that, for lazy sequences, these operations may perform
    -- lazy I\/O.
    class IOData a where
        readFile     :: MonadIO m => FilePath -> m a
        writeFile    :: MonadIO m => FilePath -> a -> m ()
        getLine      :: MonadIO m => m a
        hGetContents :: MonadIO m => Handle -> m a
        hGetLine     :: MonadIO m => Handle -> m a
        hPut         :: MonadIO m => Handle -> a -> m ()
        hPutStrLn    :: MonadIO m => Handle -> a -> m ()
        hGetChunk    :: MonadIO m => Handle -> m a
    instance IOData ByteString.ByteString where
        readFile :: forall (m :: * -> *). MonadIO m => FilePath -> m ByteString
    readFile = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (FilePath -> IO ByteString) -> FilePath -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO ByteString
    ByteString.readFile
        writeFile :: forall (m :: * -> *). MonadIO m => FilePath -> ByteString -> m ()
    writeFile FilePath
    fp = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> ByteString -> IO ()
    ByteString.writeFile FilePath
    fp
        getLine :: forall (m :: * -> *). MonadIO m => m ByteString
    getLine = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ByteString
    ByteString.getLine
        hGetContents :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetContents = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (Handle -> IO ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO ByteString
    ByteString.hGetContents
        hGetLine :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetLine = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (Handle -> IO ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO ByteString
    ByteString.hGetLine
        hPut :: forall (m :: * -> *). MonadIO m => Handle -> ByteString -> m ()
    hPut Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> ByteString -> IO ()
    ByteString.hPut Handle
    h
        hPutStrLn :: forall (m :: * -> *). MonadIO m => Handle -> ByteString -> m ()
    hPutStrLn Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> ByteString -> IO ()
    ByteString8.hPutStrLn Handle
    h
        hGetChunk :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetChunk = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (Handle -> IO ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    ByteString.hGetSome Int
    defaultChunkSize
    instance IOData LByteString.ByteString where
        readFile :: forall (m :: * -> *). MonadIO m => FilePath -> m ByteString
    readFile = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (FilePath -> IO ByteString) -> FilePath -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO ByteString
    LByteString.readFile
        writeFile :: forall (m :: * -> *). MonadIO m => FilePath -> ByteString -> m ()
    writeFile FilePath
    fp = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> ByteString -> IO ()
    LByteString.writeFile FilePath
    fp
        getLine :: forall (m :: * -> *). MonadIO m => m ByteString
    getLine = (ByteString -> ByteString) -> m ByteString -> m ByteString
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ByteString -> ByteString
    LByteString.fromStrict (IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ByteString
    ByteString.getLine)
        hGetContents :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetContents = IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (Handle -> IO ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO ByteString
    LByteString.hGetContents
        hGetLine :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetLine = (ByteString -> ByteString) -> m ByteString -> m ByteString
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ByteString -> ByteString
    LByteString.fromStrict (m ByteString -> m ByteString)
    -> (Handle -> m ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString)
    -> (Handle -> IO ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO ByteString
    ByteString.hGetLine
        hPut :: forall (m :: * -> *). MonadIO m => Handle -> ByteString -> m ()
    hPut Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> ByteString -> IO ()
    LByteString.hPut Handle
    h
        hPutStrLn :: forall (m :: * -> *). MonadIO m => Handle -> ByteString -> m ()
    hPutStrLn Handle
    h ByteString
    lbs = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ do
            Handle -> ByteString -> IO ()
    LByteString.hPutStr Handle
    h ByteString
    lbs
            Handle -> ByteString -> IO ()
    ByteString8.hPutStrLn Handle
    h ByteString
    ByteString.empty
        hGetChunk :: forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetChunk = (ByteString -> ByteString) -> m ByteString -> m ByteString
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ByteString -> ByteString
    LByteString.fromStrict (m ByteString -> m ByteString)
    -> (Handle -> m ByteString) -> Handle -> m ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> m ByteString
    forall a (m :: * -> *). (IOData a, MonadIO m) => Handle -> m a
    forall (m :: * -> *). MonadIO m => Handle -> m ByteString
    hGetChunk
    instance IOData Text.Text where
        readFile :: forall (m :: * -> *). MonadIO m => FilePath -> m Text
    readFile = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (FilePath -> IO Text) -> FilePath -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO Text
    Text.readFile
        writeFile :: forall (m :: * -> *). MonadIO m => FilePath -> Text -> m ()
    writeFile FilePath
    fp = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> Text -> IO ()
    Text.writeFile FilePath
    fp
        getLine :: forall (m :: * -> *). MonadIO m => m Text
    getLine = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO Text
    Text.getLine
        hGetContents :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetContents = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (Handle -> IO Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO Text
    Text.hGetContents
        hGetLine :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetLine = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (Handle -> IO Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO Text
    Text.hGetLine
        hPut :: forall (m :: * -> *). MonadIO m => Handle -> Text -> m ()
    hPut Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> Text -> IO ()
    Text.hPutStr Handle
    h
        hPutStrLn :: forall (m :: * -> *). MonadIO m => Handle -> Text -> m ()
    hPutStrLn Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> Text -> IO ()
    Text.hPutStrLn Handle
    h
    #if MIN_VERSION_text(0, 11, 3)
        hGetChunk :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetChunk = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (Handle -> IO Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO Text
    Text.hGetChunk
    #else
        -- Dangerously inefficient!
        hGetChunk =
            liftIO . handleEOF . liftM Text.singleton . System.IO.hGetChar
          where
            handleEOF = handle $ \e ->
                if isEOFError e
                    then Prelude.return Text.empty
                    else throwIO e
    #endif
    instance IOData LText.Text where
        readFile :: forall (m :: * -> *). MonadIO m => FilePath -> m Text
    readFile = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (FilePath -> IO Text) -> FilePath -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO Text
    LText.readFile
        writeFile :: forall (m :: * -> *). MonadIO m => FilePath -> Text -> m ()
    writeFile FilePath
    fp = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> Text -> IO ()
    LText.writeFile FilePath
    fp
        getLine :: forall (m :: * -> *). MonadIO m => m Text
    getLine = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO Text
    LText.getLine
        hGetContents :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetContents = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (Handle -> IO Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO Text
    LText.hGetContents
        hGetLine :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetLine = IO Text -> m Text
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> m Text) -> (Handle -> IO Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO Text
    LText.hGetLine
        hPut :: forall (m :: * -> *). MonadIO m => Handle -> Text -> m ()
    hPut Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> Text -> IO ()
    LText.hPutStr Handle
    h
        hPutStrLn :: forall (m :: * -> *). MonadIO m => Handle -> Text -> m ()
    hPutStrLn Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> Text -> IO ()
    LText.hPutStrLn Handle
    h
        hGetChunk :: forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetChunk = (Text -> Text) -> m Text -> m Text
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Text -> Text
    LText.fromStrict (m Text -> m Text) -> (Handle -> m Text) -> Handle -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> m Text
    forall a (m :: * -> *). (IOData a, MonadIO m) => Handle -> m a
    forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetChunk
    instance (Char ~ c) => IOData [c] where
        readFile :: forall (m :: * -> *). MonadIO m => FilePath -> m [c]
    readFile = IO [c] -> m [c]
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO [c] -> m [c]) -> (FilePath -> IO [c]) -> FilePath -> m [c]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO [c]
    FilePath -> IO FilePath
    Prelude.readFile
        writeFile :: forall (m :: * -> *). MonadIO m => FilePath -> [c] -> m ()
    writeFile FilePath
    fp = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> ([c] -> IO ()) -> [c] -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> FilePath -> IO ()
    Prelude.writeFile FilePath
    fp
        getLine :: forall (m :: * -> *). MonadIO m => m [c]
    getLine = IO [c] -> m [c]
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO [c]
    IO FilePath
    Prelude.getLine
        hGetContents :: forall (m :: * -> *). MonadIO m => Handle -> m [c]
    hGetContents = IO [c] -> m [c]
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO [c] -> m [c]) -> (Handle -> IO [c]) -> Handle -> m [c]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO [c]
    Handle -> IO FilePath
    System.IO.hGetContents
        hGetLine :: forall (m :: * -> *). MonadIO m => Handle -> m [c]
    hGetLine = IO [c] -> m [c]
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO [c] -> m [c]) -> (Handle -> IO [c]) -> Handle -> m [c]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO [c]
    Handle -> IO FilePath
    System.IO.hGetLine
        hPut :: forall (m :: * -> *). MonadIO m => Handle -> [c] -> m ()
    hPut Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> ([c] -> IO ()) -> [c] -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> FilePath -> IO ()
    System.IO.hPutStr Handle
    h
        hPutStrLn :: forall (m :: * -> *). MonadIO m => Handle -> [c] -> m ()
    hPutStrLn Handle
    h = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> ([c] -> IO ()) -> [c] -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> FilePath -> IO ()
    System.IO.hPutStrLn Handle
    h
        hGetChunk :: forall (m :: * -> *). MonadIO m => Handle -> m [c]
    hGetChunk = (Text -> [c]) -> m Text -> m [c]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Text -> [c]
    Text -> FilePath
    Text.unpack (m Text -> m [c]) -> (Handle -> m Text) -> Handle -> m [c]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> m Text
    forall a (m :: * -> *). (IOData a, MonadIO m) => Handle -> m a
    forall (m :: * -> *). MonadIO m => Handle -> m Text
    hGetChunk