Breaking change: RWS monad now supports Error type
As with the previous release that refactored the Reader
monad to have better error handling. I have now done the same for the RWS
monad.
Breaking changes
RWS
doesn't now return a tuple and instead returnsRWSResult<MonoidW, R, W, S, A>
which has a lot of the same functionality asReaderResult<A>
but with additional functionality bespoke to theRWS
monad (ToReader()
,ToWriter()
,ToState()
).- The old
RWSResult
static class has been replaced and you should now use theRWS
andRWSFail
constructors in thePrelude
to construct the pure and failure monads.
Code-gen
The LanguageExt.CodeGen
library has been updated to work with the new RWS
monad and is the easiest way to work with Reader
and RWS
monads (Writer
and State
will be added soon).
For those that have missed it, this:
namespace TestBed
{
[RWS(WriterMonoid: typeof(MSeq<string>),
Env: typeof(IO),
State: typeof(Person),
Constructor: "Pure",
Fail: "Error" )]
public partial struct Subsys<T>
{
}
}
Will generate:
namespace TestBed
{
public partial struct Subsys<T>
{
readonly internal LanguageExt.RWS<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T> __comp;
internal Subsys(LanguageExt.RWS<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T> comp) => __comp = comp;
public static Subsys<T> Pure(T value) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, value));
public static Subsys<T> Error() => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, LanguageExt.Common.Error.Bottom));
public static Subsys<T> Error(string message) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, LanguageExt.Common.Error.New(message)));
public static Subsys<T> Error(Exception exception) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, LanguageExt.Common.Error.New(exception)));
public static Subsys<T> Error(LanguageExt.Common.Error error) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, error));
public static Subsys<T> Error(string message, Exception exception) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, LanguageExt.Common.Error.New(message, exception)));
public Subsys<U> Map<U>(Func<T, U> f) => new Subsys<U>(__comp.Map(f));
public Subsys<U> Select<U>(Func<T, U> f) => new Subsys<U>(__comp.Map(f));
public Subsys<U> Bind<U>(Func<T, Subsys<U>> f) => new Subsys<U>(__comp.Bind(a => f(a).__comp));
public Subsys<U> SelectMany<U>(Func<T, Subsys<U>> f) => new Subsys<U>(__comp.Bind(a => f(a).__comp));
public Subsys<V> SelectMany<U, V>(Func<T, Subsys<U>> bind, Func<T, U, V> project) => new Subsys<V>(__comp.Bind(a => bind(a).__comp.Map(b => project(a, b))));
public (TryOption<T> Value, LanguageExt.Seq<string> Output, TestBed.Person State) Run(TestBed.IO env, TestBed.Person state) => __comp.Run(env, state);
public Subsys<T> Filter(Func<T, bool> f) => new Subsys<T>(__comp.Where(f));
public Subsys<T> Where(Func<T, bool> f) => new Subsys<T>(__comp.Where(f));
public Subsys<T> Do(Action<T> f) => new Subsys<T>(__comp.Do(f));
public Subsys<T> Strict() => new Subsys<T>(__comp.Strict());
public Seq<T> ToSeq(TestBed.IO env, TestBed.Person state) => __comp.ToSeq(env, state);
public Subsys<LanguageExt.Unit> Iter(Action<T> f) => new Subsys<LanguageExt.Unit>(__comp.Iter(f));
public Func<TestBed.IO, TestBed.Person, State> Fold<State>(State state, Func<State, T, State> f)
{
var self = this;
return (env, s) => self.__comp.Fold(state, f).Run(env, s).Value.IfNoneOrFail(state);
}
public Func<TestBed.IO, TestBed.Person, bool> ForAll(Func<T, bool> f)
{
var self = this;
return (env, s) => self.__comp.ForAll(f).Run(env, s).Value.IfNoneOrFail(false);
}
public Func<TestBed.IO, TestBed.Person, bool> Exists(Func<T, bool> f)
{
var self = this;
return (env, s) => self.__comp.Exists(f).Run(env, s).Value.IfNoneOrFail(false);
}
public Subsys<T> Local(Func<TestBed.IO, TestBed.IO> f) => new Subsys<T>(LanguageExt.Prelude.local<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>(__comp, f));
public Subsys<(T, U)> Listen<U>(Func<LanguageExt.Seq<string>, U> f) => new Subsys<(T, U)>(__comp.Listen(f));
public Subsys<T> Censor(Func<LanguageExt.Seq<string>, LanguageExt.Seq<string>> f) => new Subsys<T>(__comp.Censor(f));
}
public static partial class Subsys
{
public static Subsys<T> Pure<T>(T value) => Subsys<T>.Pure(value);
public static Subsys<T> Error<T>() => Subsys<T>.Error();
public static Subsys<T> Error<T>(string message) => Subsys<T>.Error(message);
public static Subsys<T> Error<T>(string message, Exception exception) => Subsys<T>.Error(message, exception);
public static Subsys<T> Error<T>(Exception exception) => Subsys<T>.Error(exception);
public static Subsys<T> Error<T>(LanguageExt.Common.Error error) => Subsys<T>.Error(error);
public static Subsys<T> asks<T>(Func<TestBed.IO, T> f) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, f(env)));
public static Subsys<TestBed.IO> ask => new Subsys<TestBed.IO>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, TestBed.IO>.New(state, env));
public static Subsys<TestBed.Person> get => new Subsys<TestBed.Person>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, TestBed.Person>.New(state, state));
public static Subsys<T> gets<T>(Func<TestBed.Person, T> f) => new Subsys<T>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, T>.New(state, f(state)));
public static Subsys<LanguageExt.Unit> put(TestBed.Person value) => new Subsys<LanguageExt.Unit>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, LanguageExt.Unit>.New(value, default(LanguageExt.Unit)));
public static Subsys<LanguageExt.Unit> modify(Func<TestBed.Person, TestBed.Person> f) => new Subsys<LanguageExt.Unit>((env, state) => LanguageExt.RWSResult<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, LanguageExt.Unit>.New(f(state), default(LanguageExt.Unit)));
public static Subsys<T> local<T>(Subsys<T> ma, Func<TestBed.IO, TestBed.IO> f) => ma.Local(f);
public static Subsys<T> Pass<T>(this Subsys<(T, Func<LanguageExt.Seq<string>, LanguageExt.Seq<string>>)> ma) => new Subsys<T>(ma.__comp.Pass());
public static Subsys<T> pass<T>(Subsys<(T, Func<LanguageExt.Seq<string>, LanguageExt.Seq<string>>)> ma) => new Subsys<T>(ma.__comp.Pass());
public static Subsys<(T, U)> listen<T, U>(Subsys<T> ma, Func<LanguageExt.Seq<string>, U> f) => ma.Listen(f);
public static Subsys<T> censor<T>(Subsys<T> ma, Func<LanguageExt.Seq<string>, LanguageExt.Seq<string>> f) => ma.Censor(f);
public static Subsys<LanguageExt.Unit> tell(LanguageExt.Seq<string> what) => new Subsys<LanguageExt.Unit>(tell<LanguageExt.ClassInstances.MSeq<string>, TestBed.IO, LanguageExt.Seq<string>, TestBed.Person, LanguageExt.Unit>(what));
public static Subsys<LanguageExt.Seq<string>> ReadAllLines(string fileName) => ask.Map(__env => __env.ReadAllLines(fileName));
public static Subsys<LanguageExt.Unit> WriteAllLines(string fileName, LanguageExt.Seq<string> lines) => ask.Map(__env => __env.WriteAllLines(fileName, lines));
public static Subsys<int> Zero => ask.Map(__env => __env.Zero);
public static Subsys<string> Name => get.Map(__env => __env.Name);
public static Subsys<string> Surname => get.Map(__env => __env.Surname);
}
}
Thereby making it much easier to work with the RWS
monad.