    {-# LANGUAGE ForeignFunctionInterface #-}
    module FileIO(FHandle,open,write,flush,close) where
    import System.Posix(Fd(Fd),
                        openFd,
                        fdWriteBuf,
                        closeFd,
                        OpenMode(WriteOnly),
                        defaultFileFlags,
                        stdFileMode
                       )
    import Data.Word(Word8,Word32)
    import Foreign(Ptr)
    import Foreign.C(CInt(..))

    data FHandle = FHandle Fd

    -- should handle opening flags correctly
    open :: FilePath -> IO FHandle
    open :: FilePath -> IO FHandle
    open filename :: FilePath
    filename = (Fd -> FHandle) -> IO Fd -> IO FHandle
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Fd -> FHandle
    FHandle (IO Fd -> IO FHandle) -> IO Fd -> IO FHandle
    forall a b. (a -> b) -> a -> b
    $ FilePath -> OpenMode -> Maybe FileMode -> OpenFileFlags -> IO Fd
    openFd FilePath
    filename OpenMode
    WriteOnly (FileMode -> Maybe FileMode
    forall a. a -> Maybe a
    Just FileMode
    stdFileMode) OpenFileFlags
    defaultFileFlags

    write :: FHandle -> Ptr Word8 -> Word32 -> IO Word32
    write :: FHandle -> Ptr Word8 -> Word32 -> IO Word32
    write (FHandle fd :: Fd
    fd) data' :: Ptr Word8
    data' length :: Word32
    length = (ByteCount -> Word32) -> IO ByteCount -> IO Word32
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteCount -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (IO ByteCount -> IO Word32) -> IO ByteCount -> IO Word32
    forall a b. (a -> b) -> a -> b
    $ Fd -> Ptr Word8 -> ByteCount -> IO ByteCount
    fdWriteBuf Fd
    fd Ptr Word8
    data' (ByteCount -> IO ByteCount) -> ByteCount -> IO ByteCount
    forall a b. (a -> b) -> a -> b
    $ Word32 -> ByteCount
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    length

    -- Handle error values?
    flush :: FHandle -> IO ()
    flush :: FHandle -> IO ()
    flush (FHandle (Fd c_fd :: CInt
    c_fd)) = CInt -> IO CInt
    c_fsync CInt
    c_fd IO CInt -> IO () -> IO ()
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    foreign import ccall "fsync" c_fsync :: CInt -> IO CInt

    close :: FHandle -> IO ()
    close :: FHandle -> IO ()
    close (FHandle fd :: Fd
    fd) = Fd -> IO ()
    closeFd Fd
    fd