languageext Either.Map/Bind with a Task in the right position [英] languageext Either.Map/Bind with a Task in the Right position

查看:189
本文介绍了languageext Either.Map/Bind with a Task in the right position的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为C#使用了工具包 languageext 软件包,并且遇到了与任何一个类,当右值是某种任务。由于某些原因,这导致挂起:

  var res = repo.GetAccountWithID(accountID)
.Map(c => filesServiceCustomer.Initialize(c))
.Bind(t => t.Result);

这里, GetAccountWithID 返回一个< Exception,Account> Initialize 方法都需要 Account 和返回任务< Either< Exception,bool>> 。但是,似乎 Map 绑定呼叫挂起。



有没有人有任何想法可能会导致这种情况或对此做些什么?

解决方案

(我是language-ext项目的作者)。除非 Task 本身阻塞 - Map 和<$ c,否则表达式没有根本原因挂起$ c> Bind 是微不足道的函数,不会做任何特别聪明的事情,绝对不会做任何同步或类似的事情。

  public class Account:NewType< Account 

我将这段代码添加到了lang-ext的单元测试中, ,单元>
{
public account(Unit _):base(unit){}
}

< Exception,Account> GetAccountWithID(int accountId)=>
Account.New(unit);

任务<要么< Exception,bool>>初始化(帐户c)=>
Task.FromResult(Right< Exception,bool>(true));

[Fact]
public void StackOverflowQuestion()
{
int accountID = 0;

var res = GetAccountWithID(accountID)
.Map(c => Initialize(c))
.Bind(t => t.Result);

$ / code>

值得一提的是,调用<$ c不是很好的做法$ c> .Result 在任务上。您绝对可以利用language-ext中的其他功能为您提供更好的服务:



例如:

<$ (c)
select r; getAccountWithID(accountID).AsTask()
从r中返回一个p $ p> var task =

AsTask 提升<例外,帐户> 转换为任务<任一<例外,帐户>> ,这意味着它可用于LINQ表达式初始化(它也返回一个任务)。



如果您从根本上反对LINQ语法,那么您可以这样做:

  var task = GetAccountWithID(accountID).AsTask ).BindT(初始化); 

任务然后是任务<任何<例外,bool>> 您可以等待

  var res =(等待任务).IfLeft(false); 

另一招(如果您使用的版本 2.0。* )将使用 Sequence 来翻转内部和外部单体:

  var res = task.Sequence(); 

这会将任务< Either< Exception,bool>> 转换为可以匹配的< Exception,Task< bool>> >。显然这取决于你最喜欢的用途。

I am using the toolkit languageext package for C# and am running into a problem with the Either class when the Right value is some kind of Task. For some reason this is causing a hang:

        var res = repo.GetAccountWithID(accountID)
            .Map(c => filesServiceCustomer.Initialize(c))
            .Bind(t => t.Result);

Here, GetAccountWithID returns an Either<Exception, Account> and the Initialize method take an Account and returns a Task<Either<Exception, bool>>. However, it would appear that either the Map or Bind calls are hanging.

Does anyone have any idea what might be causing this or what to do about it?

解决方案

(I'm the author of the language-ext project). There's no fundamental reason for your expression to hang, other than if the Task itself is blocking - Map and Bind are trivial functions that don't do anything particularly clever, and definitely don't do any synchronisation or anything like that. I just added this code to the unit tests in lang-ext, and it returns fine:

    public class Account : NewType<Account, Unit>
    {
        public Account(Unit _) : base(unit) { }
    }

    Either<Exception, Account> GetAccountWithID(int accountId) =>
        Account.New(unit);

    Task<Either<Exception, bool>> Initialize(Account c) =>
        Task.FromResult(Right<Exception, bool>(true));

    [Fact]
    public void StackOverflowQuestion()
    {
        int accountID = 0;

        var res = GetAccountWithID(accountID)
            .Map(c => Initialize(c))
            .Bind(t => t.Result);
    }

One thing it's worth mentioning is that it's not great practice to call .Result on a task. You can definitely leverage other features in language-ext to make this work better for you:

For example:

    var task = from c in GetAccountWithID(accountID).AsTask()
               from r in Initialize(c)
               select r;

AsTask lifts the Either<Exception, Account> into a Task<Either<Exception, Account>>, which then means it's usable in a LINQ expression with Initialize (which also returns a Task).

If you're fundamentally opposed to the LINQ syntax, then you can do:

    var task = GetAccountWithID(accountID).AsTask().BindT(Initialize);

task is then a Task<Either<Exception, bool>> which you can await:

    var res = (await task).IfLeft(false);

Another trick (if you're using version 2.0.*) is to use Sequence which flips the inner and outer monads:

    var res = task.Sequence();

That will turn the Task<Either<Exception, bool>> into a Either<Exception, Task<bool>> which you can match on. Obviously it depends on your use-case as to what's most appropriate.

这篇关于languageext Either.Map/Bind with a Task in the right position的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆