将我们的parser转换成Monad
还记得我们上一篇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的更多相关文章
- Gson将字符串转换成JsonObject和JsonArray
以下均利用Gson来处理: 1.将bean转换成Json字符串: public static String beanToJSONString(Object bean) { return new Gso ...
- 【HIVE】sql语句转换成mapreduce
1.hive是什么? 2.MapReduce框架实现SQL基本操作的原理是什么? 3.Hive怎样实现SQL的词法和语法解析? 连接:http://www.aboutyun.com/thread-20 ...
- Python 爬虫:把廖雪峰教程转换成 PDF 电子书
写爬虫似乎没有比用 Python 更合适了,Python 社区提供的爬虫工具多得让你眼花缭乱,各种拿来就可以直接用的 library 分分钟就可以写出一个爬虫出来,今天尝试写一个爬虫,将廖雪峰老师的 ...
- Java对象转换成xml对象和Java对象转换成JSON对象
1.把Java对象转换成JSON对象 apache提供的json-lib小工具,它可以方便的使用Java语言来创建JSON字符串.也可以把JavaBean转换成JSON字符串. json-lib的核心 ...
- Gson解析json字符串、json数组转换成对象
实体类: public class Product { private int id; private String name; private String date; public int get ...
- 自制 Python小工具 将markdown文件转换成Html文件
今天看到了一个Python库,名为markdown.瞬间就给了我一个灵感,那就是制作一个将markdown文件转换成html文件的小工具. 我的实验环境 操作系统: Windows 7 64位 旗舰版 ...
- 用Python将word文件转换成html(转)
用Python将word文件转换成html 序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上.客户大大说,要智能推送!要掌握节奏!要深度学习!要 ...
- python3将docx转换成pdf,html文件,pdf转doc文件
直接上代码 # -*- encoding:utf-8 -*- """ author:lgh 简单的doc转pdf,html,pdf转doc脚本 依赖库pdfminer3k ...
- 将字符串转换成xml并取得对应的值
如数据库中有一个字段保存了xml格式的一串字符串: <?xml version="1.0" encoding="utf-16"?><Array ...
随机推荐
- wget 批量下载网站目录下的文件
执行如下命令就会自动下载 http://www.iyunwei.com/docs/ 下面的所有文件: wget -nd -r -l1 --no-parent http://www.iyunwei.co ...
- Firebug全了解
Firebug是firefox下的一个扩展,能够调试所有网站语言,如Html,Css等,但FireBug最吸引人的就是javascript调试功能,使用起来非常方便,而且在各种浏览器下都能使用(IE, ...
- MySQL常用增删改查等操作语句
修改数据库的字符集 mysql>use mydb mysql>alter database mydb character set utf8;创建数据库指定数据库的字符集 ...
- 爬取表格类网站数据并保存为excel文件
本文转载自以下网站:50 行代码爬取东方财富网上市公司 10 年近百万行财务报表数据 https://www.makcyun.top/web_scraping_withpython6.html 主要学 ...
- vue 对图片进行拖拽到另一个位置
1.拖动元素代码: 使用html5原生拖拽属性,在需要拖拽的图片中添加draggable="true"属性,并使用v-on添加拖动事件 2.被放置的区域事件代码: 使用html5原 ...
- 浅谈 Mysql
数据库一些基本的概念 Mysql 基础操作 Mysql 数据类型 Mysql 表的完整性约束 Mysql 表的操作 Mysql 数据增删改查语句 Mysql 多表查询 Mysql 索引原理及分类 My ...
- Mycat连接数据库之后导致表名全小写的问题分析研究
初步研究:通过部署发现在Mycat中部署逻辑表表名大小写混合时,在Mycat连接后出现全变小.容易造成错误逻辑表(按混合表名创建物理表): 可能拯救的方法: 1.Linux下部署安装MySQL,默认不 ...
- MySQL 面试题目
1, mysql的复制原理以及流程. (1)先问基本原理流程,3个线程以及之间的关联. (2)再问一致性,延时性,数据恢复. (3)再问各种工作遇到的复制bug的解决方法 2,mysql中myis ...
- HDU多校赛第9场 HDU 4965Fast Matrix Calculation【矩阵运算+数学小知识】
难度上.,,确实...不算难 问题是有个矩阵运算的优化 题目是说给个N*K的矩阵A给个K*N的矩阵B(1<=N<=1000 && 1=<K<=6),先把他们乘起 ...
- ZOJ 3717
这题是二分+2SAT. 总结一下SAT题的特征.首先,可能会存在二选一的情况,然后会给出一些矛盾.据这些矛盾加边,再用SAT判定. 这一道题好像不能直接用printf("%0.3lf&quo ...