如何在C ++中使用std :: optional

时间:2016-10-12 16:03:08

标签: c++ functional-programming monads c++17

在C ++ 17 std::optional中,我对这个决定感到高兴,直到我看到ref。我知道来自Scala,Haskell和Java 8的Optional / Maybe,其中可选的是monad并遵循monadic定律。在C ++ 17实现中不是这种情况。如何使用std::optionalmapflatMap / bind这样的函数,我应该如何使用std::optional vs来获得优势,例如返回{{1}如果它无法计算结果,或者来自函数的-1? 对我来说更重要的是,为什么nullptr没有设计为monad,有原因吗?

3 个答案:

答案 0 :(得分:4)

  

我应该如何使用std :: optional,像map和flatMap / bind

这样的函数
Haskell中的

Maybe在没有fmap的情况下完全可用,它表示可能存在或不存在的值。它还为类型系统带来了区别,因此您需要处理这两种情况。

  

使用std :: optional vs的优点是什么,例如返回-1,或者如果无法计算结果,则从函数中获取nullptr?

您如何知道错误情况是什么?是0-1MAX_INTnullptr还是其他什么?如果我同时拥有unsigned intint返回值以及之前返回的int版本-1,您应该将它们更改为MAX_INT或让它们返回不同的值? std::optional避免了这个问题。

  

对我来说更重要的是,为什么没有std :: optional设计成monad,有原因吗?

C ++目前是否有monad?除了与容器之外的抽象不同之外,实际上还没有一种方法可以添加该功能。

答案 1 :(得分:4)

提出了P0798r0提案,以及相关的实施here on Github。该提案还涉及一般的monadic接口提议,以及类似可用的std :: expected。这些也可以实现。

答案 2 :(得分:2)

可以定义bindreturn超过std::optional,因此从这个意义上说它仍然是Monad。

例如,可能bind

template<typename T1, typename T2>
std::optional<T2> bind(std::optional<T1> a, std::function< std::optional<T2>(T1)> f) {
   if(a.has_value()) return f(a.value());
   return std::optional<T2>{};
 }

实际上定义它可能很有用。

至于为什么标准库没有附带这个或类似的东西,我认为答案是该语言中首选的样式之一。