欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

Linq怎么支持Monad

发布时间:2025/5/22 41 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Linq怎么支持Monad 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
Linq怎么支持Monad

  在上一篇创建了我们的第一个Monad, Identity<T>. 我们确定了类型要变成Monad, 它必须有一个type constructor(Identity<T>), 和两个方法,Bind与ToIdentity

//a function Bind, allows us to compose Identity returning functionspublic static Identity<B> Bind<A,B>(this Identity<A>a, Func<A,Identity<B>func>) { return func(a.Value); }public static Identity<T>ToIdentity<T>(tis T Value) { return new Identity<T>(value); }

我也提到了在C#里 Bind有个不同的名字,SelectMany,它是为IEnumerable<T>定义的扩展方法, 如你所知,IEnumerable<T>也是一个Monad,实际上它是C#里Monad的代表.

        今天我们来看下如何为Identity<T>实现SelectMany, 并且去掉繁琐的lambda表达式

Linq要求我们写一个函数来结合Bind和To****的功能,SelectMany,SelectMany签名必须如下:

Identity<C>SelectMany<A,B,C>(this Identity<A>a,Func<A,Identity<B>>func,Func<A,B,C>select)

它看起来像Bind函数,只是多了一个select参数,它以A,B为参数,返回C。 并且有一个不同的返回类型Identity<C>,替代Identity<B>. 如果你的amplified实现了SelectMany方法,在执行Linq的"from x in y"表达式时会转换为SelectMany的调用.

让我们将SelectMany实现为一个扩展方法:

public static Identity<C>SelectMany<A,B,C>(this Identity<A>a,Func<A,Identity<B>>func, Func<A,B,C>select) { return ??? }

现在要根据参数类型来写出实现,首先我们知道要返回Identity<C>, 只有select Func可以返回C,我们可以调用ToIdentity将C转换为Identity<C>

public static Identity<C>SelectMany<A,B,C>(this Identity<A>a,Func<A,Identity<B>>func, Func<A,B,C>select) { return select(???).ToIdentity(); }

传什么给select呢, 第一个参数是A,我们可以调用a.Value得到A, 第二个参数B,我们可以通过Bind函数得到B

public static Identity<C>SelectMany<A,B,C>(this Identity<A>a,Func<A,Identity<B>>func, Func<A,B,C>select) { return (a.Value,a.Bind(func).Value).ToIdentity(); }

让我们展开Bind函数,在这里Bind并没有多大用

public static Identity<C>SelectMany<A,B,C>(this Identity<A>a,Func<A,Identity<B>>func, Func<A,B,C>select) { return select(a.Value,func(a.Value).Value).ToIdentity(); }

我们已经为Identity<T>实现了SelectMany. 现在我们可以用Linq语法替换我们上一篇的lambda表达式:

var result="Hello World!".ToIdentity().Bind(a=>7.ToIdentity().Bind(b=>(new DateTime(2010,1,11)).ToIdentity().Bind(c=>(a+", "+b.ToString()+", "+c.ToShortDateString()).ToIdentity())));var result=from a in "Hello World".ToIdentity()from b in 7.ToIdentity()from c in (new DateTime(2010,1,11)).ToIdentity()select a+", "+b.ToString()+", "+c.ToShortDateString();Console.WriteLine(result.Value);

是不是清晰很多?通过新视角看Linq和Monad, 我们可以把"from x in y"看做是Monad式的赋值,将将右侧的amplified value 赋值给左侧的unamplified type。

实际上你可以对任何WhatEver<T>使用Linq语法,而不仅仅是IEnumerable<T>。如果你想使用其他linq 语法如where,let,join等,你必须实现对应的方法, 他们都可以使用Bind创建

posted on 2016-06-27 23:30 哨兵 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/phenixyu/p/5621915.html

总结

以上是生活随笔为你收集整理的Linq怎么支持Monad的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。