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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是成长股 公司业绩还是市场潜力都非常
- 下一篇: docker入门及安装