返回信息流模拟Monad主要是为了写语法分析器简便。
之前试着用C#模拟,好麻烦。。改用C++之后一路通畅。
只要支持模板、支持lambda表达式或函数指针或委托,且能重载运算符的强类型语言其实都可以。。
```cpp
template<typename T>
class Monad {
public:
T* val;
Monad() {
}
Monad(T* a) {
this->val = a;
}
};
template<typename T,typename K>
Monad<K>* operator>>(Monad<T>* a, function<Monad<K>*(T*)> f) { //>>=,chain
return f(a->val);
}
template<typename T>
Monad<T>* id(T* a) { //pack,return
return new Monad<T>(a);
}
```
然后Parser就可以写成这样。。。
```cpp
class Parser {
public:
int id;
Parser() {
}
Parser(int id) {
this->id = id;
}
virtual void Parse() {
// do something
}
};
Parser* p = new Parser(1);
Monad<Parser>* pm = id(p);
//StatementParser, IfParser, ForParser, ExpressionParser,EndParser 是 Parser的子类
function<Monad<Parser>*(Parser*)> f = [](Parser* a) {
a->Parse();
return new Monad<Parser>(new StatementParser(a->id + 1));
};
function<Monad<Parser>*(Parser*)> g = [](Parser* a) {
a->Parse();
return new Monad<Parser>(new IfParser(a->id + 1));
};
function<Monad<Parser>*(Parser*)> h = [](Parser* a) {
a->Parse();
return new Monad<Parser>(new ForParser(a->id + 1));
};
function<Monad<Parser>*(Parser*)> m = [](Parser* a) {
a->Parse();
return new Monad<Parser>(new ExpressionParser(a->id + 1));
};
function<Monad<Parser>*(Parser*)> end = [](Parser* a) {
a->Parse();
return new Monad<Parser>(new EndParser(a->id + 1));
};
Monad<Parser>* parserS = pm >> f >> g >> h >> m >> end; //做的基础设施就是为了这样串起来
```
只需要把各环节的小的Parser函数f定义好,串联起来形成各种文法表达式,再汇集起来,就是完整的组合子风格语法分析器(Parser Combinator)。
我仅仅写的是一个示例,基本啥事没做。
后面的事。。。慢慢做吧。
也许就没有后续了
这是一条镜像帖。来源:北邮人论坛 / cpp / #97199同步于 2018/2/8
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
哈哈哈哈,C++模拟Haskell的Monad还是蛮轻松的
cocoyimasa
2018/2/8镜像同步10 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
编译原理+Haskell语言基础。。。至少知道语法分析器是个啥。Monad有毛用。
【 在 ztinpn 的大作中提到: 】
: 不明觉厉,实现这个需要什么基础呀?
对啊,哈哈哈哈。我觉得只有写编译器的时候编程才有趣,其他时候都是被迫的。
【 在 poiuasd 的大作中提到: 】
: 帮顶,发现还是写编译器或者解释器好玩。。
几乎没人问过我编译原理,大多数面试官不敢问。只有一个微软面试官跟我浅浅聊过几句
【 在 lucashood 的大作中提到: 】
: 可以的
: 前几天去面试还问到了编译原理的东西,不过不深,哈哈