Comments (4)
As noted above, I have removed EitherAsync
, OptionAsync
, TryAsync
-- this library is now against async
/await
because of the unnecessary code-bloat it causes. It is also part of a bigger move to monad transformers.
There is now just one officially supported async type: IO<A>
which is the IO monad. The IO monad is very lightweight and simple, but it can be composed with other transformer monads to augment its capability.
Also, see my blog for details on what's happening with v5.
The current set of transformer monads are:
ContT
- continuationsIdentityT
EitherT
OptionT
TryT
ValidationT
ResourceT
- resource tracking (use
,release
)ReaderT
WriterT
StateT
Proxy
- pipes base transformer
So, for the monadic types that were compositions of other types, they've mostly gone, but you can now use the transformers to get that exact functionality:
EitherAsync<L, R>
isEitherT<L, IO, R>
OptionAsync<A>
isOptionT<IO, A>
TryAsync<A>
isTryT<IO, A>
TryOption<A>
isTryT<Option, A>
TryOptionAsync<A>
isTryT<OptionT<IO>, A>
(three levels of monadic types stacked)
This also means the much requested (but never implemented) ValidationAsync
can also be built:
ValidationT<F, IO, A>
So, there's now no limitation to how you can stack your types.
You can use it like so:
var mx = EitherT<Error, IO, int>.Right(100);
var my = EitherT<Error, IO, int>.Right(100);
var mz = EitherT<Error, IO, int>.Left(Errors.Cancelled);
var mr = from x in mx
from y in my
from z in mz
select x + y + z;
IO<Either<Error, int>> ior = mr.Run().As();
Either<Error, int> r = ior.Run();
You'll notice that the Run
section at the end is more involved. Each Run
unwraps the outer monad.
You'll also notice that there's no awaiting of the result. There's no need for that now as the thread automatically yields (when waiting for an IO operation to complete) without the need to use the async/await machinery.
If you want to lift an asynchronous operation then you have a few options.
First, you need to construct an IO monad. This can be done with one of the following instructions:
IO.Pure(x)
- lifts a pure value into the IO monadIO.Fail(Error)
- lifts a failure value into the IO monadIO.lift(f)
- wheref
is a synchronous functionIO.liftAsync(f) - where
f` is an asynchronous function
The Prelude
also has a liftIO
with liftVIO
variants for ValueTask
functions. It also has some additional overloads that lift for specific monad transformers tasks, so if you have a Task<Either<L, R>>
then calling liftIO
with the task will get you a EitherT<L, IO, R>
.
As well as the functions listed above -- which you'll want to use most of the time -- each transformer monad has a LiftIO
static function you can call:
/// <summary>
/// Lifts a given monad into the transformer
/// </summary>
/// <param name="monad">Monad to lift</param>
/// <returns>`EitherT`</returns>
public static EitherT<L, M, A> LiftIO(IO<A> monad) =>
Lift(M.LiftIO(monad));
/// <summary>
/// Lifts a given monad into the transformer
/// </summary>
/// <param name="monad">Monad to lift</param>
/// <returns>`EitherT`</returns>
public static EitherT<L, M, A> LiftIO(IO<Either<L, A>> monad) =>
Lift(M.LiftIO(monad));
With the example above you can do this:
var mr = from x in mx
from y in my
from v in liftIO(e => System.IO.File.ReadAllTextAsync(path, e.Token))
from z in mz
select x + y + z;
The e
variable is an EnvIO
type that carries the CancellationToken
, CancellationTokenSource
, and SynchronizationContext
.
If you look at the set of static functions available for the IO monad, you'll see all the extra functionality that is now available for any transformer stack that uses it. Including, cancellation, scheduled retries and repeats, local cancellation environments, thread forking and yielding. So, there's a ton more power than the original EitherAsync
.
The one thing to note though: IO
is designed to be very simple and lightweight. So, it throws exceptions if there's a failure. So, when you call the final Run
to realise the Either<L, R>
, it can throw:
IO<Either<Error, int>> ior = mr.Run().As(); // this is ok
Either<Error, int> r = ior.Run(); // this can throw
Obviously, because we don't know what the L
is there's no way of constructing one from an Exception
. So, you need your own error handling strategy for whatever is the Left
value of your EitherT
.
My suggestion is to wrap up the running logic into bespoke extension method for your types:
public static class YourErrorExtension
{
public static Either<YourError, A> Run<A>(this EitherT<YourError, IO, A> ma)
{
try
{
return ma.Run().As().Run();
}
catch (Exception e)
{
return MapExceptionToYourError(e);
}
}
}
Another thing you can do is to wrap the transformer EitherT<L, IO, R>
into a new type:
public record EitherAsync<L, R>(EitherT<L, IO, R> runEitherT)
{
// ... add functions that map to `EitherT` and then rewrap in an EitherAsync
}
This approach isn't easy to do because you have to repeat the interface for EitherT
. My plan is to make this easy through code-generation. If you want to see what this looks like you can take a look at the Eff
monad; it is a wrapper around StateT<ResourceT<IO>>>
.
So, yeah, v5
is the once in a decade change to this library that will hopefully set it up for the next decade. It's not free for existing code-bases, but it's much more powerful once you've migrated to it.
Also, note, I do not advise migrating to v5
whilst its still in an alpha or beta phase. Any migration is likely to be quite a bit of work and, if there are bugs, there may be times when I don't have the bandwidth to respond.
from language-ext.
I'm pretty sure it was removed, see this
from language-ext.
and I'm about to report a bug(?) in EitherAsync
pipe operation... but I guess it's no longer needed 😔
from language-ext.
Got it, thank you!
from language-ext.
Related Issues (20)
- Can't cancel efffect HOT 13
- Missing some functions in OptionAsync HOT 1
- TryAsync prelude should have an overload that takes a Task HOT 1
- Creating a custom Either type with a custom fixed Left type. HOT 1
- Conflict between LangugeExt Extension methods and LINQ Extension methods HOT 2
- AffRxExtensions.Consume blocks the waiting thread on IObservable's completion
- How to make LanguageExt.CodeGen work on Unity? HOT 2
- Seq<EitherAsync<A, B>>.SequenceParallel does not preserve order HOT 14
- FileIO bug for Test when opening new file for writing
- Directory IO bug for Test when enumerating files
- Simple Kickstart Project available? CodeGen tool is outdated? dotnet8 HOT 1
- Implicit conversion of int? to Option<int> HOT 2
- SequenceParallel performance degradation in 4.4.8 HOT 1
- Refit.ApiException: 'An error occured deserializing the response.'
- Constructor not found for LanguageExt.LongRange HOT 1
- Alternative to inherit from Fin and other monads
- Add `DoAsync` to Either types (and maybe others) HOT 2
- Release build fails for a big application HOT 5
- v5 resource tracking issue? HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from language-ext.