当我理解了 monad 在 c++/python 中的用途后,我终于开始了解 monad 了,它允许您将以下形式的函数链接在一起T -> Generic<U>
。例如,如果您有
readfile = [](string s) -> optional<string> {...};
http_request = [](string s) -> optional<int> {...};
inverse = [](int i) -> optional<int> {...}
然后绑定>>= :: optional<T> -> (T -> optional<U>) -> optional<U>
具有完全正确的签名以允许您编写这些函数
optional{"myfile"} >>= readfile >>= http_request >>= inverse;
// or in haskell
read_request_inverse = (>>= inverse) . (>>= http_request) . readfile
而不是手动写出短路条件
[]() -> optional<int>
{
auto message = readfile("myfile");
if (!message)
return nullopt
auto number = http_request(*message)
if (!number)
return nullopt
return inverse(*number)
}
我认为让我困惑的是没有区分链式绑定和嵌套绑定(Bartosz Milewski 演示了 C++ 范围 https://bartoszmilewski.com/2014/10/17/c-ranges-are-pure-monadic-goodness/)并分别理解它们
auto triples =
for_each(ints(1), [](int z) {
return for_each(ints(1, z), [=](int x) {
return for_each(ints(x, z), [=](int y) {
return yield_if(x*x + y*y == z*z, std::make_tuple(x, y, z));
});
});
});
这只是列表理解
triples = [(x, y, z) | z <- [1..]
, x <- [1..z]
, y <- [x..z]
, x^2 + y^2 == z^2]
另外,我相信我被这样一个事实绊倒了:读者、作者和状态单子只是试图逆向工程副作用(我不完全确定这不会重新引入不纯过程/子例程的问题),所以在多范式语言中没有用处,在多范式语言中您只能产生真正的(合理限制的)副作用。
So monadic optional<T>
/result<T,E>
seems highly useful in c++/python/rust, and monadic ranges/lists might be useful solving coding challenges but not really for real life problems (edit: I've actually started using flatmap
/views::for_each
it a lot for simplifying "business logic").
所以我的问题是是否还有其他 monad 的例子可以证明 monad 在多范式语言中的有用性?