代码之家  ›  专栏  ›  技术社区  ›  stakx - no longer contributing Saravana Kumar

对IEnumerable以外的类型(monad?)进行操作的LINQ查询表达式-可能的用途?

  •  13
  • stakx - no longer contributing Saravana Kumar  · 技术社区  · 15 年前

    我正在读这本书 Real-world functional programming by Tomas Petricek and Jon Skeet 我很难理解计算表达式这一节 1)

    通过这本书,我学到了这一点-与我以前的经历相反- LINQ查询表达式不限于 IEnumerable<T> ,但也可以处理其他自定义类型。 这对我来说似乎非常有趣,我想知道是否存在查询表达式语法( from x in ... select ... )很合适。


    显然,这样的自定义类型称为 计算类型 ,它们被描绘成与 monads in Haskell 绑定

    在函数式编程中,这两个操作的类型签名是(我认为):

    //    Bind      :    M<A'> -> (A' -> B') -> M<B'>
    //
    //    Return    :    A' -> M<A'>
    

    M 是单子类型的名称。

    在C#中,这对应于:

    Func< M<A>, Func<A,B>, M<B> >   Bind;
    
    Func< A, M<A> >                 Return;
    

    原来林克 Enumerable.Select M := IEnumerable .

    利用这些知识,我现在可以编写一个自定义的计算类型 IEnumerable

    // my custom computation type:
    class Wrapped<A>
    {
        // this corresponds to the Return operation:
        public Wrapped(A value)
        {
            this.Value = value;
        }
    
        public readonly A Value;
    }
    
    static class Wrapped
    {
        // this corresponds to the Bind operation:
        public static Wrapped<B> Select<A, B>(this Wrapped<A> x, Func<A,B> selector)
        {
            return new Wrapped<B>(selector(x.Value));
        }
    }
    

    现在我可以用 Wrapped<T> 在LINQ查询表达式中,例如:

    Wrapped<int> wrapped = new Wrapped<int>(41);
    
    Wrapped<int> answer  = from x in wrapped   // works on int values instead 
                           select x + 1;       // of Wrapped<int> values!
    

    当然这个例子不是很有用,但是它演示了 可以使查询表达式执行与集合无关的操作 ,例如,使用某种类型包装和展开值。


    上面的计算类型似乎不是很有用。因此,我想知道,除了处理集合之外,还有什么其他合理的用途可以使用LINQ查询表达式?


    1)

    4 回复  |  直到 15 年前
        1
  •  4
  •   stakx - no longer contributing Saravana Kumar    15 年前

    即使我不喜欢这样做(因为这感觉有点像作弊),我想这次我必须回答我自己的问题。

    我在这个问题上想得更多了。我的问题有点天真。归根结底,LINQ查询表达式(例如。 from in where select …)以及 foreach

    • foreach公司 IEnumerator<T> GetEnumerator() IEnumerable<T> 正好满足了这个条件。

    • 类似地,LINQ查询表达式根据一些定义良好的规则进行翻译,例如。 from x in xs where x > 0 select -x xs.Where(x => x > 0).Select(x => -x) . 只要某个类型实现了部分或全部查询运算符方法,该类型就可以与LINQ一起用于几乎任何目的。

    因为LINQ查询表达式的结构非常严格 . 你总是需要 在里面 选择 …也总是需要的。如果结果表达式的“语言”不适合特定的潜在场景,则任何其他关键字( let orderby , groupby 等)不会改善情况。LINQ的设计很清楚地考虑到了一个目标,即数据的查询,而得到的语法实际上对LINQ的限制超出了可能需要的范围。

    我将LINQ用于查询数据以外的用途的可能性与F#计算表达式的可能性进行了比较,它们似乎更灵活,因为没有那么多必需的关键字。这使得它们更适合于更多的场景。

        2
  •  3
  •   Mau    15 年前

    LinqToTwitter以一种不同寻常的方式使用LINQ。“from”子句中的内容在逻辑上不是可枚举类型。 看看资料来源:)

        3
  •  3
  •   Marc Gravell    15 年前

    思想:

    • IEnumerable<T> 拉动模型)
    • 反应性框架/反应性扩展-另一个与LINQ语法非常不同的事件模型
    • 我使用LINQ查询语法编写了一个线程API(ab);我不是100%相信它,所以放弃它-但它是有趣的;习惯于 from ( SelectMany 完全地 与可枚举项无关
        4
  •  1
  •   sara    9 年前

    它的用处和单子在Haskell中的用处是一样的。实现一个 Either<TLeft, TRight> 例如,键入并提供查询理解实现。这可以用来编写更多的功能性代码,在这些代码中,您可以使用内置的错误处理和日志等在用例中编写操作。基本上,看看Haskell之类的语言(或F#表示离家较近的语言),了解monad在实际代码中的用法。

    现在,问题当然是,这可能不是非常地道的C代码,即使它可以工作和维护,等等。重要的是不要反对这种语言,不要编写只有你才能理解的代码。至少,你的团队应该“参与进来”。

    推荐文章