Implement basic Stream ability operations.
In functional languages, functions like filter, map, and
reduce are very common. Implement a series of basic functional combinators for a stream ability
without using existing functions. You'll need to write your own ability handlers for this.
💡 We're going to call this ability MyStream to avoid conflicting with the existing Stream ability in the standard library.
The operations you'll need to implement are:
MyStream.fromList (given a list of elements, create a stream of elements )MyStream.toList (given a stream of elements, materialize it to a list)MyStream.toListWithResult (given a stream of elements, materialize it to a list alongside the result of the stream function)MyStream.ignore (given a stream of elements, ignore the emitted values, returning the results of the stream function)MyStream.filter (given a predicate and a MyStream, return the MyStream of all items for which predicate(item) is true);MyStream.map (given a function and a MyStream, return the MyStream of the results of applying function(item) on all items);MyStream.flatMap (given a function which produces a MyStream and a MyStream, return the MyStream of the results of applying function(item) on all items)A Stream is a Unison ability that is used to emit values.
You might use the Stream ability if you have a function which should produce values as a secondary effect while it is being called. For example, this function returns the last value of the list, but emits a running total as each element is seen:
emitRunningTotal : '{Stream Nat} Nat
emitRunningTotal = 'let
use Nat +
List.foldLeft (
acc a -> let
runningTotal = acc + a
Stream.emit runningTotal
a
) 0 [1,2,3,4,5]
We can materialize the Stream as a List alongside the return value of the function which produces it with an ability handler:
> Stream.toListWithResult! emitRunningTotal
â§©
([1, 3, 5, 7, 9], 5)
Sign up to Exercism to learn and master Unison with 52 exercises, and real human mentoring, all for free.