<!doctype linuxdoc system>

<!-- Documentation for the Haskell Ports Library
 -->

<article>

<title>The Haskell Ports Library
<author>Manuel M. T. Chakravarty, <tt/chak@cse.unsw.edu.au/
<date>v0.2, 15 July 2000
<abstract>
Ports are an abstraction for modeling variables, i.e., entities whose values
evolve over time, without the need to resort to mutable variable, such as
<tt/IORef/s.  More precisely, a port represents all values that a
time-dependent variable successively takes as a stream, where each element of
the stream corresponds to a state change - we can also say that a port
represents a time series.  Moreover, a port supports concurrent construction
of the time series, or stream of values.  Ports are ideally suited for
functional GUI interfaces that completely avoid the use of mutable variables.
It is planned to extend the library to interaction between different processes
possibly located on distinct processing nodes.
</abstract>

<toc>

<p>
<bf>Copyright &amp; Distribution</bf>
<p>
Copyright (c) [1999..2000] by <htmlurl
url="http://www.cse.unsw.edu.au/~chak/" name="Manuel M. T. Chakravarty">.  
The manual is distributed under the terms GNU Free Documentation License
available from
<url url="http://www.fsf.org/copyleft/fdl.html">.
<p>
The master copy of this document is at <url
url="http://www.cse.unsw.edu.au/~chak/haskell/ports/">; the source is in
SGML, which allows you to produce a selection of standard formats, including
HTML and Postscript.

<p>
<bf>Contributions</bf>
<p>
If you have any comments, suggestions, or contributions, please send them to
<htmlurl url="mailto:chak@cse.unsw.edu.au" name="chak@cse.unsw.edu.au">.


<sect>Introduction
<p>
This documentation is still very rudimentary.  It merely describes the headers
of the two main modules of the library.  For installation instructions, have a
look at the file <tt/INSTALL/ in the source distribution.
<p>
The script <tt/ports-config/ can be used to obtain the necessary compile and
runtime flags of the current HPL installation:
<p>
<tscreen><verb>
Usage: ports-config [OPTIONS] [LIBRARIES]
Options:
	[--system=HS]
	[--prefix[=DIR]]
	[--exec-prefix[=DIR]]
	[--version]
	[--libs]
	[--cflags]
</verb></tscreen>
<p>


<sect>Interface of the Module <tt/SVars/
<p>
This module provides a simple form of <em/single assignment variables./  The
following type represents single assignment variables.
<p>
<tscreen>
data V a
</tscreen>
<p>
Single assignment variables can only be created within the <tt/IO/ monad;
otherwise, referential transparency would be compromised.
<p>
<tscreen>
newV :: IO (V a)
</tscreen>
<p>
However, the value of a single assignment variables can be <em/accessed/
outside of the monad.  This is save, as single assignment variables are only
instantiated monotonically, i.e., once such a variable is bound, the value can
never change again.
<p>
<tscreen>
valV :: V a -> a
</tscreen>
<p>
If a single assignment variable is accessed while no value is yet bound to the
variable, the thread accessing the variable is suspended.  Only when the
variable is, eventually, bound, the reading thread is allowed to continue.
Thus, a computation can never observe an unbound single assignment variable,
which together with the monotonicity (mentioned above) guarantees
referential transparency.
<p>
Single assignment variables can be bound <em/within/ the <tt/IO/ monad with an
expression of the form <tt/svar &lt;&lt; value/, where <tt/svar/ is a single
assignment variable and <tt/value/ the value that is to be associated with the
variable
<p>
<tscreen>
(&lt;&lt;) :: V a -> a -> IO ()
</tscreen>
<p>
Furthermore, this module provides a symmetric fork/join operation:
<p>
<tscreen>
(&) :: IO a -> IO b -> IO (a, b)
</tscreen>
<p>
The operation models parallel composition, which terminates after both of the
concurrent subcomputations terminated.


<sect>Interface of the Module <tt/Ports/
<p>
Ports are an abstraction for modeling variables whose values evolve
over time without the need to resort to mutable variable, such as
<tt/IORef/s.  More precisely, a port represents all values that a
time-dependent variable successively takes as a stream, where each
element of the stream corresponds to a state change - we can also say
that a port represents a time series.

<sect1>Ports and Port Filters
<p>
Ports containing values of type <tt/a/ are represented as
<p>
<tscreen>
data Port a
</tscreen>
<p>
One or more streams can be associated with a port, which contain (a subset) of
the values that the port assumes while evolving over time.  The values
in the output stream are determined by the messages or events that are
directed to the port.
<p>
<em/Port filters/ serve as guards that control the values that a port can
take, i.e., they screen the incoming messages and may adjust incoming port
values (e.g., to ensure that all values appearing in the output stream of a
port stay within certain bounds)  or even reject them.
<p>
<tscreen>
type PortFilter a = a -> a -> Maybe a
</tscreen>
<p>
The first argument given to a port filter is the value of the port at the
moment where a given incoming messages is processed and the second argument is
that incoming value.  The port filter can decide to entirely reject the value
by returning <tt/Nothing/, or it can return the value that should be assumed
by the port next.  This can, but need not be the same as the incoming value.

<sect1>Creating and Closing Ports
<p>
A port without a port filter (i.e., one that accepts any incoming message) is
created by 
<p>
<tscreen>
newPort :: a -> IO (Port a)
</tscreen>
<p>
The argument constitutes the initial value of the port, but it never appears
in any output stream of the port.  This value is mainly important for
filtering ports, which are created with
<p>
<tscreen>
newFilteringPort :: a -> PortFilter a -> IO (Port a)
</tscreen>
<p>
These ports apply the given port filter to any value before placing it into
the output stream.
<p>
Ports can be closed, which means that all corresponding streams are ended.
<p>
<tscreen>
closePort :: Port a -> IO ()
</tscreen>
<p>
It can be checked whether a port is closed or not.
<p>
<tscreen>
isClosedPort :: Port a -> IO Bool
</tscreen>

<sect1>Accessing and Querying Ports
<p>
The following function obtains a stream containing the values assumed by the
port as it evolves over time.
<p>
<tscreen>
listenToPort :: Port a -> IO [a]
</tscreen>
<p>
Note that while this stream has to be obtained within the <tt/IO/ monad, the
stream itself can be processed purely functional (i.e., an observer of the
port need not be coded in the monad).  A stream contains the values assumed by
the port <em/after/ <tt/listenToPort/ is executed; previous values are not
contained in the stream.
<p>
The following operation sends the second argument to the port given in the
first argument:
<p>
<tscreen>
(&lt;--) :: Port a -> a -> IO ()
</tscreen>
<p>
As it is sometimes convenient to send a list of values to a port, the
following function, which is usually more efficient than the previous one, is
also available:
<p>
<tscreen>
(&lt;==) :: Port a -> [a] -> IO ()
</tscreen>
<p>
More generally, we can send a function that transforms the current port value
to a port:
<p>
<tscreen>
(&lt;-$) :: Port a -> (a -> a) -> IO ()
</tscreen>
<p>
For example, <tt/p &lt;-$ (+1)/ would increment the current value of the port
<tt/p/ by one.  Obviously, <tt/p &lt;-$ const x/ corresponds to <tt/p &lt;--
x/.
<p>
Finally, the current value of a port can be obtained within the <tt/IO/
monad.
<p>
<tscreen>
peekIntoPort :: Port a -> IO (Maybe a)
</tscreen>
<p>
This function should only be used for purposes like initialisation.  It breaks
the idea of observing the time series as a whole instead of individual
elements, i.e., snapshots of the port and when multiple threads are sending
messages to a port, the order of a <tt/peekIntoPort/ call with respect to the
messages is usually not deterministic.  If the port is closed,
<tt/Nothing/ is returned.

<sect1>Port Chaining
<p>
Two ports may be chained together, which means that one port's output stream
is passed into a second port after having applied a mapping function:
<p>
<tscreen>
chainPorts :: (a -> b) -> Port a -> Port b -> IO ()
</tscreen>

<sect1>Port Linking
<p>
Two ports can be to be synchronised, or <em/linked,/ so that they share all
incoming events.  
<p>
<tscreen>
(&lt;-&gt;) :: Port a -> Port a -> IO ()
</tscreen>
<p>
In fact, they can even have different domains and use translation functions to
map values between their domains.
<p>
<tscreen><verb>
linkPorts :: (a -> b) -> (b -> a) -> Port a -> Port b -> IO ()
</verb></tscreen>
<p>

<sect1>Proxy Ports
<p>
Ports that represent an external state as a port are called <em/proxy ports./
To keep a proxy port in sync with some external state, we use <em/Port
notifiers,/ which either the port of a change in the external state or vice
versa.  The argument to a notifier is the new value.  Depending on the kind of
the notifier, it puts this value into the port or updates the external state.
<p>
<tscreen>
type PortNotifier a = a -> IO ()
</tscreen>
<p>
When a port is created, it is given the notifier that it should use to notify
the external state of changes in the port.  As a result it does not only
produce the port, but also a second notifier that is to be invoked whenever
the external state changes.
<p>
<tscreen><verb>
newProxyPort :: a -> PortNotifier a -> IO (Port a, PortNotifier a)
</verb></tscreen>
<p>
The produced notifier will take care that no feedback loop is introduced.


<sect>Bug Reports and Suggestions
<p>
Please address any bug reports and suggestions to <htmlurl
url="mailto:chak@cse.unsw.edu.au" name="chak@cse.unsw.edu.au">.  A good bug
report contains information on the used operating system and Haskell compiler
as well as the version of the Haskell Ports Library that you have been using.
You can obtain the version information by running <tt/ports-config --version/.
If possible a concise example illustrating your problem would be appreciated.


<sect>Copyright
<p>
The Haskell Ports Library is Copyright (c) 2000 Manuel M. T. Chakravarty

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the 
Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
Boston, MA  02111-1307  USA.

This manual is Copyright (c) 2000 by Manuel M. T. Chakravarty. 
Permission is granted to copy, distribute and/or modify this document under
the terms of the GNU Free Documentation License, Version 1.1 or any later
version published by the Free Software Foundation; with no Invariant Sections,
with no Front-Cover Texts, and with the no Back-Cover Texts.  A copy of the
license is included in the section entitled "GNU Free Documentation License".

<sect>GNU Free Documentation License
<p>
The GNU Free Documentation License is available at
<url url="http://www.fsf.org/copyleft/fdl.html">.


<sect>Release Notes

<sect1>Version 0.2.1 "Pacific Air"
<p>
<itemize>
<item>Configuration works with ghc 4.08.1
</itemize>

<sect1>Version 0.2.0 "Pacific Air"
<p>
<itemize>
<item>Proxy ports
<item>Port linking
</itemize>
(Adding the <tt/yield/ operations that are commented out in this version leads
to mysterious core dumps.)

<sect1>Version 0.1.1
<p>
First release.


</article>
