【发布时间】:2022-06-18 16:20:09
【问题描述】:
当我通过允许您将 T -> Generic<U> 形式的函数链接在一起来了解它们在 c++/python 中的用途时,我终于开始了解 monad。例如,如果您有
readfile = [](string s) -> optional<string> {...};
http_request = [](string s) -> optional<int> {...};
inverse = [](int i) -> optional<int> {...}
然后 bind >>= :: 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 demonstrates with c++ ranges)并分别理解它们
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]
另外,我相信我被以下事实绊倒了:reader、writer 和 state monad 只是试图对副作用进行逆向工程(我不完全确定这不会重新引入不纯过程/子例程的问题),因此在多范式语言中没有用处,在这种语言中,您只能有真正的(明显受限的)副作用。
所以 monadic optional<T>/result<T,E> 在 c++/python/rust 中似乎非常有用,而 monadic 范围/列表可能有助于解决编码挑战,但 并不是真正解决现实生活中的问题(编辑:我已经开始大量使用flatmap/views::for_each 来简化“业务逻辑”。
所以我的问题是,还有其他单子示例可以证明单子在多范式语言中的有用性吗?
【问题讨论】:
标签: monads