我正在用 C 撰寫一些相對實用的風格代碼,并試圖避免為它發明一個壞名字。為此,我試圖盡可能在 Haskell 中使用同構概念的名稱。(需要明確的是,我對 Haskell 了解不多,但閱讀它已經很有啟發性。)
如果我正確地完成了 Haskell 輸入,我相信我正在尋找名稱的概念將具有以下簽名:
someName :: (Monad m1, Monad m2) => (a -> m1 b) -> (m2 a -> m1 m2 b)
這個想法是你有一個適合用來系結型別 monad 的m1函式,然后你將它轉換成一個適合系結m1包含m2值的值的函式。
我不能很好地撰寫 Haskell 來舉個例子,但這里是偽 C 說明我想要什么,使用std::optionaland 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)));
這個概念有名字嗎?如果不是,是因為它在某些方面存在缺陷,還是可以用更簡單的部分構建?
uj5u.com熱心網友回復:
你寫的型別簽名基本上是一樣的:
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
哪里f = m1和t = m2。
m2但如果是任意單子,它并不總是有效。一定是Traversable。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528506.html
上一篇:串列中的Haskell資料型別
下一篇:適用于Num和List的函式
