StreamT non-termination issue resolved
This question was raised where a StreamT fold was not terminating. The issue was slightly deeper than I initially thought. SourceT took a different approach to terminating a reducer than Source. SourceT used M.Pure as a terminating value whereas Source has a dedicated structure, Reduced, which has a Continue flag, indicating whether any reducer is complete or not.
I thought M.Pure was enough to terminate a stream, but it wasn't sufficient, I made a mistake on that one. So, I've updated all of the SourceT reducers to now return K<M, Reduced<A>> which allows streams like SourceT.forever to spot when a 'downstream' reducer has ended the stream and can therefore terminate, rather than continue forever heating up the processor.
StreamT is still completely without any form of decent test coverage, so still be cautious using it.
There are now four reducing methods on StreamT which allow for different return values in the reducer function:
S- just the pure reduced valueK<M, A>- the lifted reduced valueReduced<S>- the pure reduced value with theContinueflag (in case you want to use this in other reducers)K<M ,Reduced<S>>- the lifted reduced value with theContinueflag (in case you want to use this in other reducers)
public K<M, S> Reduce<S>(S state, Reducer<A, S> reducer) =>
ReduceM(state, (s, x) => M.Pure(reducer(s, x)));
public K<M, S> FoldReduce<S>(S state, Func<S, A, S> reducer) =>
ReduceM(state, (s, x) => M.Pure(Reduced.Continue(reducer(s, x))));
public K<M, S> ReduceM<S>(S state, ReducerM<M, A, S> reducer) =>
ReduceInternalM(state, (s, mx) => mx.Bind(x => reducer(s, x))).Map(r => r.Value);
public K<M, S> FoldReduceM<S>(S state, Func<S, A, K<M, S>> reducer) =>
ReduceInternalM(state, (s, mx) => mx.Bind(x => reducer(s, x).Map(Reduced.Continue))).Map(r => r.Value);