languageext Either.Map/Bind with a Task in the right position [英] 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屋!