jac*_*bsa 3 monads haskell functional-programming monad-transformers
我正在用 C++ 编写一些相对函数式风格的代码,并试图避免为其起一个坏名字。为此,我尽可能坚持 Haskell 中同构概念的名称。(需要明确的是,我不太了解 Haskell,但阅读它非常有启发性。)
如果我正确地完成了 Haskell 打字,我相信我正在寻找名称的概念将具有以下签名:
someName :: (Monad m1, Monad m2) => (a -> m1 b) -> (m2 a -> m1 m2 b)
Run Code Online (Sandbox Code Playgroud)
这个想法是,您有一个适合用于绑定类型 monad 的函数m1,并将其转换为适合绑定m1包含m2值的值的函数。
我不能很好地编写 Haskell 来给出一个例子,但这里是伪 C++ 说明我想要的,使用std::optional和absl::StatusOr:
// A silly example of a bind function for absl::StatusOr<int>.
absl::StatusOr<int> AddTwoUnless17(int x) {
if (x == 17) {
return absl::InternalError("can't add two to 17!")
}
return x + 2;
}
// Convert AddTwoUnless17 into a bind function for
// absl::StatusOr<std::optional<int>>. The resulting logic is:
//
// * If the input is an error, propagate that error.
// * If the input is std::nullopt, return std::nullopt.
// * If the input is 17, return an error.
// * Otherwise return the input plus two.
//
// Here we have:
//
// m1: absl::StatusOr
// m2: std::optional
//
std::function<absl::StatusOr<std::optional<int>>(std::optional<int>) f =
someName(AddTwoUnless17);
CHECK_EQ(
absl::CancelledError(),
f(absl::StatusOr<std::optional<int>>(absl::CancelledError())));
CHECK_EQ(
std::nullopt,
f(absl::StatusOr<std::optional<int>>(std::nullopt)));
CHECK_EQ(
absl::InternalError("can't add two to 17!"),
f(absl::StatusOr<std::optional<int>>(17)));
CHECK_EQ(
13,
f(absl::StatusOr<std::optional<int>>(11)));
Run Code Online (Sandbox Code Playgroud)
这个概念有名字吗?如果不是,是因为它在某些方面存在缺陷,还是可以用更简单的部分构建?
您编写的类型签名基本上与以下内容相同:
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
Run Code Online (Sandbox Code Playgroud)
哪里f = m1和t = m2.
m2但如果是任意单子,它并不总是有效。一定是Traversable。