C# 如何在有结果时停止执行并将结果返回给monad
我特别需要一种反向的单子,当它是“无”时,它将继续尝试获取一个值,并保留它获取的第一个有效值 我试图概括我在这里的意思:C# 如何在有结果时停止执行并将结果返回给monad,c#,linq,monads,C#,Linq,Monads,我特别需要一种反向的单子,当它是“无”时,它将继续尝试获取一个值,并保留它获取的第一个有效值 我试图概括我在这里的意思: public void Test() { var r = from x in SomeActionToGetResult() from y in Stop() from z in SomeOtherActionToGetResult() select x | y | z; } public Ma
public void Test()
{
var r = from x in SomeActionToGetResult()
from y in Stop()
from z in SomeOtherActionToGetResult()
select x | y | z;
}
public Maybe<Result> SomeActionToGetResult()
{
return new Result().Unit();
}
public Maybe<Result> SomeOtherActionToGetResult()
{
return new Result().Unit();
}
public Maybe<Result> Stop()
{
return new Nothing<Result>();
}
Unit函数与普通函数类似,但Bind函数给我带来了麻烦:
public static Maybe<U> Bind<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k)
{
if (!m.HasAValidValue)
return k(m.Value);
return m; // <--- problem right here
}
公共静态可能绑定(这可能是m,Func k)
{
如果(!m.HasAValidValue)
返回k(m值);
返回m;//(这可能对您没有任何帮助,在这种情况下,我将删除它。如果您正在与单子玩耍,这很可能是在教我的祖母吸鸡蛋,但是…)
您是否知道C#已经在语言级别上使用了此功能
如果您需要以更基于库的形式实现这一点,这很好(我会看看我能想到什么),但是如果您可以使用现有的操作符,我会的
编辑:我试过你的拼图,我认为基本上它不适合LINQ。问题主要与LINQ在SelectMany
中期望的类型有关。例如,你的第二行有效地转换为:
SomeActionToGetResult().SelectMany(x => Stop(), (x, y) => new { x, y });
这里的问题是:
- 在
Stop()
表达式中,我们不使用x
的值,从逻辑上讲,我们不能使用,因为我们只希望在x
的计算结果为None
- 匿名类型不一定与
SomeActionToGetResult()
的返回类型的T
部分的类型相同,因此我们无法将其转换为Maybe
。我们必须引入一个新类型来提取它们
然后,当我们有:
select x | y | z
从逻辑上讲,这是你唯一能拥有的东西吗?拥有它有意义吗
select z | y | x
如果是这样,那意味着什么?我们无法避免SomeActionToGetResult()
从执行开始,因为扩展方法只对该方法调用的结果起作用……因此,要么必须忽略投影,并且您始终计算x
,然后计算y
,然后计算z
——要么您接受排序不会始终准确保留
从根本上说,我怀疑你这里没有真正的单子,否则我会期望它合适——但我在数学方面没有足够的能力来说。(这可能对你没有任何帮助,在这种情况下,我将删除它。如果你在玩单子,这很可能是在教我祖母吸鸡蛋,但是……)
您是否知道C#已经在语言级别上使用了此功能
如果您需要以更基于库的形式实现这一点,这很好(我会看看我能想到什么),但是如果您可以使用现有的操作符,我会的
编辑:我试过你的拼图,我认为基本上它不适合LINQ。问题主要与LINQ在SelectMany
中期望的类型有关。例如,你的第二行有效地转换为:
SomeActionToGetResult().SelectMany(x => Stop(), (x, y) => new { x, y });
这里的问题是:
- 在
Stop()
表达式中,我们不使用x
的值,从逻辑上讲,我们不能使用,因为我们只希望在x
的计算结果为None
- 匿名类型不一定与
SomeActionToGetResult()
的返回类型的T
部分的类型相同,因此我们无法将其转换为Maybe
。我们必须引入一个新类型来提取它们
然后,当我们有:
select x | y | z
从逻辑上讲,这是你唯一能拥有的东西吗?拥有它有意义吗
select z | y | x
如果是这样,那意味着什么?我们无法避免SomeActionToGetResult()
从执行开始,因为扩展方法只对该方法调用的结果起作用……因此,要么必须忽略投影,并且您始终计算x
,然后计算y
,然后计算z
——要么您接受排序不会始终准确保留
从根本上说,我怀疑你这里没有真正的单子,否则我会期望它合适-但我在数学方面没有足够的能力来说。谢谢你的快速回答。我知道空合并运算符,我想我实际上可以使用它,但从方法返回空表示“停止处理”看起来有点模糊,我只是想让它更清楚。我的“可能”将在我的程序中命名为“停止”,只是为了熟悉这里才把它叫做:)…我最近经常碰到这个问题,现在我开始怀疑是否有可能把它说得尽可能清楚。我遇到的另一个例子是,我遇到了这个问题——空合并运算符不可用——是当monad携带多个值来确定它的b时ehavior@asgerhallas:在这种情况下,你可以使用元组
,我可以考虑实现适当的SelectMany
(etc)调用,我会看看今晚我能做些什么。尽管没有承诺……哦,那确实很好!:)@asgerhallas:已经编辑过,但我认为你不会喜欢我的结论:(感谢您的快速回答。我知道空合并运算符,我想我实际上可以使用它,但是从方法返回空表示“停止处理”似乎有点模糊,我只是想让它更清楚。我的“Maybe”将在我的程序中命名为“StopOr”,只是为了熟悉,在这里称它为Maybe:)…我最近经常碰到这个问题,现在我开始怀疑是否有可能把它说得尽可能清楚。我遇到的另一个例子是,当单子携带多个值来确定它的行为时,null合并运算符不可用。@asgerhallas:您可以使用Tuple
在这种情况下…我可以考虑为这类事情执行适当的选择许多(等)调用-我将看看今晚我能做些什么。尽管没有承诺…哦,那将是b