还记得我们上一篇delegate类型的parser吗 ,在开始本篇之前,强烈建议你复习一下这个parser定义 

public delegate Maybe<Tuple<T,string>>Parser<T>(string input)

还记得我们组合这些parser的不易吗?现在我们采用新的方式将parser转换为Monad, 我们已经知道了如何将泛型类和泛型接口转换成Monad, 同样的也可以将委托转换成Monad

首先我们实现一个ToParser方法, 它相当简单,只返回一个不消耗任何输入字符串的parser

public static Parser<T>ToParser(this T value)
{
return input=>new Just<Tuple<T,string>>(Tuple.Create(value,input))
}

接下来我们需要一个Bind方法, 回想下Bind方法的签名,记住所有的Monad Bind方法签名时一样的

public static Parser<B> Bind<A,B> (this Parser<A>a, Func<A,Parser<B>>func)()

现在我们一步步实现Bind,首先看下返回类型 Parser<B>.记住Parser<B>是一个参数为string 返回类型为Maybe<Tuple<B,string>>的函数,所以我们需要为这个函数返回一个lambda表达式

public static Parser<B>Bind<A,B>(this Parser<A> a, Func<A,Parser<B>func>)
{
input=>
{ //......
}
}

这个lambda需要返回Maybe<Tuple<B,string>>, 我们可以通过调用func返回返回Parser<B>,然后调用Parser<B>返回它:

public static Parser<B>Bind<A,B>(this Parser<A>a, Func<A,Parser<B>>func)
{
return input=>
{
var bparser=func(???); return bparser(???);
};
}

我们需要一个参数A调用func, 我们可以调用a得到它的返回值,然后从中取出A来:

public static Parser<B> Bind<A,B>(this Parser<A>a, Func<A,Parser<B>>func)
{
return input=>
{ var aMaybe=a(input); var aResult=aMaybe as Just<Tuple<A,string>>; //short circuit if parse fails if(aResult == null) return new Nothing<Tuple<B,string>>(); var aValue=aResult.Value.Item1; var bParser=func(aValue); return bParser(???);
}
}

注意我们短路了解析过程,如果有一个parser失败,这意味着任何解析器组合都会返回Nothing,如果其中一个解析器不能解析它的输入.

最后我们需要一个string 作为bParser的输入,这个值可以从parser a的返回结果里得到:

public static Parser<B> Bind<A,B>(this Parser<A>a, Func<A,Parser<B>>func)
{
return input=>
{
var aMaybe=a(input); var aResult=aMaybe as Just<Tuple<A,string>>; //short circuit if parse fails if(aResult == null) return new Nothing<Tuple<B,string>>(); var aValue=aResult.Value.Item1; var sString=aResult.Value.Item2; var bParser=func(aValue); return bParser(sString);
}
}

我们已经创建了一个Monad parser,为了使用linq的语法,我们需要实现SelectMany ,

现在我们可以只用下面三行代码来实现我们的Hello World parser.

public static Parser<C>SelectMany<A,B,C>(this Parser<A>a, Func<A,Parser<B>>func, Func<A,B,C>select)
{
a.Bind(aval=>func(aval).Bind(bval=>select(aval,bval).ToParser()));
}

var helloWorldParser=from hello in "Hello".Find()

                                    from world in "World".Find()

                                    select new (Hello=hello, World=world);

var result=helloWorldParser("HelloWorld");

Console.WriteLine(result.AsString(x=>x.Hello));

Console.WriteLine(result.AsString(x=>x.World));

//outputs

//Hello

//World

这个实现充满美感,希望你能开始了解怎样用Monad 创建复杂的逻辑,如果你想深入了解Monad parser, Nicholas Blumhardt实现的project Sprache可供参考: https://github.com/sprache/Sprache

其他Monad资源参考:

https://github.com/phenixyu/csharp-monad

将我们的parser转换成Monad的更多相关文章

  1. Gson将字符串转换成JsonObject和JsonArray

    以下均利用Gson来处理: 1.将bean转换成Json字符串: public static String beanToJSONString(Object bean) { return new Gso ...

  2. 【HIVE】sql语句转换成mapreduce

    1.hive是什么? 2.MapReduce框架实现SQL基本操作的原理是什么? 3.Hive怎样实现SQL的词法和语法解析? 连接:http://www.aboutyun.com/thread-20 ...

  3. Python 爬虫:把廖雪峰教程转换成 PDF 电子书

    写爬虫似乎没有比用 Python 更合适了,Python 社区提供的爬虫工具多得让你眼花缭乱,各种拿来就可以直接用的 library 分分钟就可以写出一个爬虫出来,今天尝试写一个爬虫,将廖雪峰老师的 ...

  4. Java对象转换成xml对象和Java对象转换成JSON对象

    1.把Java对象转换成JSON对象 apache提供的json-lib小工具,它可以方便的使用Java语言来创建JSON字符串.也可以把JavaBean转换成JSON字符串. json-lib的核心 ...

  5. Gson解析json字符串、json数组转换成对象

    实体类: public class Product { private int id; private String name; private String date; public int get ...

  6. 自制 Python小工具 将markdown文件转换成Html文件

    今天看到了一个Python库,名为markdown.瞬间就给了我一个灵感,那就是制作一个将markdown文件转换成html文件的小工具. 我的实验环境 操作系统: Windows 7 64位 旗舰版 ...

  7. 用Python将word文件转换成html(转)

    用Python将word文件转换成html   序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上.客户大大说,要智能推送!要掌握节奏!要深度学习!要 ...

  8. python3将docx转换成pdf,html文件,pdf转doc文件

    直接上代码 # -*- encoding:utf-8 -*- """ author:lgh 简单的doc转pdf,html,pdf转doc脚本 依赖库pdfminer3k ...

  9. 将字符串转换成xml并取得对应的值

    如数据库中有一个字段保存了xml格式的一串字符串: <?xml version="1.0" encoding="utf-16"?><Array ...

随机推荐

  1. wget 批量下载网站目录下的文件

    执行如下命令就会自动下载 http://www.iyunwei.com/docs/ 下面的所有文件: wget -nd -r -l1 --no-parent http://www.iyunwei.co ...

  2. Firebug全了解

    Firebug是firefox下的一个扩展,能够调试所有网站语言,如Html,Css等,但FireBug最吸引人的就是javascript调试功能,使用起来非常方便,而且在各种浏览器下都能使用(IE, ...

  3. MySQL常用增删改查等操作语句

    修改数据库的字符集    mysql>use mydb    mysql>alter database mydb character set utf8;创建数据库指定数据库的字符集    ...

  4. 爬取表格类网站数据并保存为excel文件

    本文转载自以下网站:50 行代码爬取东方财富网上市公司 10 年近百万行财务报表数据 https://www.makcyun.top/web_scraping_withpython6.html 主要学 ...

  5. vue 对图片进行拖拽到另一个位置

    1.拖动元素代码: 使用html5原生拖拽属性,在需要拖拽的图片中添加draggable="true"属性,并使用v-on添加拖动事件 2.被放置的区域事件代码: 使用html5原 ...

  6. 浅谈 Mysql

    数据库一些基本的概念 Mysql 基础操作 Mysql 数据类型 Mysql 表的完整性约束 Mysql 表的操作 Mysql 数据增删改查语句 Mysql 多表查询 Mysql 索引原理及分类 My ...

  7. Mycat连接数据库之后导致表名全小写的问题分析研究

    初步研究:通过部署发现在Mycat中部署逻辑表表名大小写混合时,在Mycat连接后出现全变小.容易造成错误逻辑表(按混合表名创建物理表): 可能拯救的方法: 1.Linux下部署安装MySQL,默认不 ...

  8. MySQL 面试题目

      1, mysql的复制原理以及流程. (1)先问基本原理流程,3个线程以及之间的关联. (2)再问一致性,延时性,数据恢复. (3)再问各种工作遇到的复制bug的解决方法 2,mysql中myis ...

  9. HDU多校赛第9场 HDU 4965Fast Matrix Calculation【矩阵运算+数学小知识】

    难度上.,,确实...不算难 问题是有个矩阵运算的优化 题目是说给个N*K的矩阵A给个K*N的矩阵B(1<=N<=1000 && 1=<K<=6),先把他们乘起 ...

  10. ZOJ 3717

    这题是二分+2SAT. 总结一下SAT题的特征.首先,可能会存在二选一的情况,然后会给出一些矛盾.据这些矛盾加边,再用SAT判定. 这一道题好像不能直接用printf("%0.3lf&quo ...