|
Session 1, 2004
Exercises: Imperative Programming in Haskell
Implement the following programs in Haskell using GHC. In some cases,
you have to use some of the non-standard libraries that come with GHC.
For this, have a look at GHC's User's
Guide and at the documentation
of the Hierachical Libraries.
Socket Programming: A Square Server
Write two programs: a server sqd and a client
sq. The server started as
sqd PORT
listens on port PORT waiting for clients to connect. A
client called as
sq HOST PORT
connects to the server running on the specified HOST and
listening on the specified PORT.
The client goes into a loop reading numbers from stdin and sending them
to the server. The server upon receiving a number, squares it and sends
it back to the client, which prints it to stdout. When the client reads
the word quit instead of a number from stdin, it
terminates. There is no special facility to terminate the server --
i.e., kill is your friend.
The first version of the server should be single threaded (i.e.,
only one client at a time can use the server). Then, revise the
implementation to make the server multi-threaded, so that it can
handle multiple simultaneous client connections. Feel free to
implement a server that provides some more interesting funcionality
than just computing squares.
Tips:
- You will find support for socket programming in the module
Network.
To use this module, you may have to pass the option
-package network to GHC when compiling or linking
code that makes use of Network.
- For concurrency, import
Control.Concurrent.
Using C Code from Haskell: Fast Strings
Strings in Haskell are represented as a lists of characters. This makes
string processing very convenient, but compared to an array-based
representation, it introduces inefficiencies that in some applications
need to be avoided.
Implement a module FastString that provides C-style NUL
terminated character arrays in Haskell by way of the following interface:
data FastString
toFS :: String -> FastString
fromFS :: FastString -> String
appendFS :: FastString -> FastString -> FastString
indexFS :: FastString -> Int -> Char
updateFS :: FastString -> Int -> Char -> FastString
In your implementation, include a C library consisting of two files
fast_string.h and fast_string.c that
implement C versions of the fast string operations. Then, make these
operations available in Haskell using the FFI.
Tips:
- Library support for the FFI is available from the modules
Foreign
and Foreign.C.
The latter provides data types and functions that are specific to
interfacing to C.
- Modules that contain
foreign declarations must be
compiled with the option -ffi.
- In the interface of
FastString, all operations are
pure (i.e., not in the IO monad). However, some of the
marshalling that you have to do requires impure operations. You can
use impure code to implement pure functions by using the function
unsafePerformIO, which you can import from
Foreign.
- Be careful when marshalling Haskell
String and
Char types, as Haskell characters support Unicode, and
thus, are typically represented by a 16bit data type. See also the
functions in module Foreign.C.String
that are available from Foreign.C.
|