将循环转换为 Maybe monad

Convert loop to Maybe monad

最近我尝试应用 Maybe monad pattern in my C# code using this 库。

我发现难以掌握的是将这样的函数转换为 Maybe 范式:

public Maybe<object> DoSomething(IReader reader)
{
    while (true)
    {
        var result = reader.Read();
        if (result == null) return Maybe<object>.Nothing;
        if (result.HasValue) return new Maybe<object>(null);
    }
}

我想用 from x in X 形式来写。此函数背后的功能是读取 IReader 直到它 returns 一个值(Maybe 有一个值)或发生错误(返回 null)。

你的 comment/question 的答案是:你不会 - 是的你可以尝试使用递归调用但是这在 C# 中可能会失败并且你更好地使用 while

from x in X 只是 monadic - bind (它被翻译成 SelectMany 函数)并且 LINQ 语法中没有直接的方法为此。

但是你可以这样写你自己的函数:

public tValue DoUntilSome<tValue>(Func<Maybe<tValue>> f)
{
    while (true)
    {
        var x = f();
        if (x.HasValue) return x.Value;
    }
}

并像这样打电话(见下文)

var result = DoUntilSome(() => TryRead(reader));

备注

首先,Maybe<object> (object) 部分有异味 - 因为您肯定想要其中的具体类型而不是通用的 object

new Maybe<object>(null)奇怪

我会建议这样的:

public Maybe<tValue> TryRead<tValue>(IReader reader)
{
    var result = reader.Read();
    if (result == null || !result.HasValue) 
        return Maybe<tValue>.Nothing;
    return new Maybe<tValue>((tValue)reader.Value);
}

当然,这部分是为了获得一些 Maybe 价值 - 你试图用 from x in X 做的事情是 monadic-bind - 你只能使用 一旦你有一个Maybe开始:

from value in TryRead<tValue>(reader)
from other in TrySomethingDifferent(value) // here is the bind
select .... 

免责声明

我没有编译任何这些(因为我懒得下载 github 项目和东西) - 你应该能够轻松解决可能隐藏在那里的任何语法错误 - 抱歉

如果您遇到重大问题,请发表评论