4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
4. FIXED POINT DEFINITIONS<br />
A stream often depends <strong>on</strong> itself as e.g. the stream of<br />
integers or fib<strong>on</strong>acci numbers shown above. This self recursi<strong>on</strong><br />
is revealed in the lazily evaluated recursive calls of<br />
the methods integersFrom or fib<strong>on</strong>acci. This recursi<strong>on</strong><br />
property can also be made more visible <strong>and</strong> be used to define<br />
a stream as a fixed point of a map <strong>on</strong> the domain of<br />
streams [6].<br />
Such maps are defined with method map of the interface<br />
StreamMap (defined in the interface Stream)<br />
interface StreamMap {<br />
Stream map(Stream stream);<br />
}<br />
<strong>and</strong> new streams are c<strong>on</strong>structed with the static generic<br />
method fixedpoint<br />
static Stream fixedPoint(StreamMap map){..}<br />
which c<strong>on</strong>structs a stream which is a fixed point of the given<br />
map.<br />
In particular, we think of maps which do not perform<br />
operati<strong>on</strong>s <strong>on</strong> their argument but rather simply include it<br />
in a new stream which is returned as result. In particular,<br />
the head element of the defined stream must not depend <strong>on</strong><br />
the argument. This way bootstrapping of the c<strong>on</strong>structi<strong>on</strong><br />
of the stream is possible.<br />
As an example we show the definiti<strong>on</strong> of the stream of<br />
<strong>on</strong>es with a fixed point. This stream is the fixed point of a<br />
map which prepends the element <strong>on</strong>e to its argument.<br />
Stream <strong>on</strong>es = fixedPoint(<br />
new StreamMap(){<br />
public Stream map(Stream s){<br />
return s.prepend(1);<br />
}<br />
}<br />
);<br />
We now discuss how the fixedPoint method is implemented<br />
for LinkedStreams <strong>and</strong> ArrayStreams. In both cases<br />
a new stream is c<strong>on</strong>structed <strong>and</strong> passed to the given map.<br />
The result is another stream of the same type. The fields<br />
of this stream are copied to the initially generated stream.<br />
This way the fixed point of the map is c<strong>on</strong>structed. The<br />
resulting code looks similar for both classes.<br />
public class LinkedStream implements Stream {<br />
private LinkedStream(){}<br />
public static Stream fixedPoint(<br />
StreamMap map){<br />
LinkedStream s1 = new LinkedStream();<br />
LinkedStream s2 = (LinkedStream)map.map(s1);<br />
s1.head = s2.head;<br />
s1.lazyTail = s2.lazyTail;<br />
return s2;<br />
} ...<br />
}<br />
public class ArrayStream implements Stream {<br />
private ArrayStream(){}<br />
public static Stream fixedPoint(<br />
StreamMap map){<br />
ArrayStream s1 = new ArrayStream();<br />
ArrayStream s2 = (ArrayStream)map.map(s1);<br />
s1.lazyCoeff = s2.lazyCoeff;<br />
return s2;<br />
} ...<br />
}<br />
Let us now define some streams as fixed points of stream<br />
maps. The first example is the periodic sequence [A, B, C,<br />
A, B, C, A, B, C, . . .]. This stream is simply the fixed point<br />
of a map which pretends the strings “A”, “B” <strong>and</strong> “C” to<br />
its argument. The statement<br />
System.out.println(<br />
fixedPoint(<br />
new StreamMap(){<br />
public Stream map(Stream s){<br />
return s.prepend("C").prepend("B").<br />
prepend("A");<br />
}<br />
}<br />
)<br />
);<br />
generates the output<br />
A B C A B C A B C A B C A B C ...<br />
Next we define the stream of integers as fixed point of a<br />
map which takes a stream, adds <strong>on</strong>e to each element <strong>and</strong><br />
prepends zero.<br />
integers = fixedPoint(<br />
new StreamMap(){<br />
public Stream map(Stream s){<br />
return s.map(<br />
new UnaryFunctor(){<br />
public Integer eval(Integer x){<br />
return x+1;<br />
}<br />
}<br />
).prepend(0);<br />
}<br />
}<br />
);<br />
This example <strong>on</strong>ly works if the prepend method does not<br />
evaluate the stream to which a new head element is prepended.<br />
Otherwise the call s.map is evaluated which results in<br />
a NullPointerExcepti<strong>on</strong> as the head element of the stream<br />
to be c<strong>on</strong>structed by this fixed point definiti<strong>on</strong> is not yet<br />
defined. As a c<strong>on</strong>sequence, this definiti<strong>on</strong> <strong>on</strong>ly works with<br />
the fixed point method of class ArrayStream.<br />
Fib<strong>on</strong>acci numbers can be expressed as the fixed point of<br />
the map<br />
f ibs → 0 : (+ f ibs (1 : f ibs))<br />
which leads to the following definiti<strong>on</strong>:<br />
class Add implements<br />
Stream.BinaryFunctor {<br />
public Integer eval(Integer x, Integer y){<br />
return x+y;<br />
}<br />
};<br />
Stream fib<strong>on</strong>acci = fixedPoint(<br />
new StreamMap() {<br />
public Stream map(Stream f){<br />
return f.zip(new Add(),<br />
f.prepend(1)).prepend(0);<br />
}<br />
}<br />
);<br />
Again, this definiti<strong>on</strong> <strong>on</strong>ly works with class ArrayStream.<br />
In this example the zip functi<strong>on</strong> accesses the head element<br />
185