This is a new I/O library for Haskell that is intended to provide a high performance API that make good use of advance operating system facilities for I/O.
Rationale and Goals
Haskell 98 specifies and number of I/O actions. All these actions accept and return
Strings perform badly and waste space. They are also conceptually the wrong type for many operations. For example, sockets receive and send bytes while file I/O often deals in terms of characters and yet both use
String while sockets should use a data type that represents binary data such as
Furthermore, do not use of efficient operating system APIs for asynchronous I/O like
To get a good idea of the different possible trade-offs in designing an I/O library here's an overview over what I/O libraries look like in other programming languages.
While Java first I/O library was built using streams the new I/O library, dubbed NIO, uses a similar concept called channels. The two basic channels,
WritableByteChannel, have a very narrow interface only providing a single read and a single write function. These two function operate on
ByteBuffers are mutable buffers that keep track on the next position available for writing and reading. Since the buffers can be allocated in a memory region used by the operating system for its native I/O operations additional copying can be avoided and the CPU might not have to be involved in the data transfer at all.
Available OS APIs for asynchronous I/O
epoll, a more efficient version of the older
poll API, since version 2.5.44. The man page describes
"An epoll set is connected to a file descriptor created by epoll_create(2). Interest for certain file descriptors is then registered via epoll_ctl(2). Finally, the actual wait is started by epoll_wait(2).
An epoll set is connected to a file descriptor created by epoll_create(2). Interest for certain file descriptors is then registered via epoll_ctl(2). Finally, the actual wait is started by epoll_wait(2)."
The API provides the following functions:
#include <sys/epoll.h> int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);
The new I/O library resides in the New I/O (NIO) module.
All I/O actions deal in terms of ByteStrings.
read :: Handle -> Int -> IO ByteString write :: Handle -> ByteString -> IO Int tell :: Handle -> IO Integer seek :: Handle -> SeekMode -> Integer -> IO () close :: Handle -> IO () truncate :: Handle -> Integer -> IO () -- should throw some kind of exception isReadable :: Handle -> IO Bool isWritable :: Handle -> IO Bool