有没有办法自动交换 monad?

Is there a way to commute monads automatically?

我写了一个程序来从一对中拉出 Maybe:

deMaybe :: (a, Maybe b) -> Maybe (a, b)
deMaybe (_, Nothing) = Nothing
deMaybe (x,Just y) = Just (x, y)

我知道 Maybe 是一个 monad 而 (,) a 是一个仿函数(在其他类型类中)。我想知道是否缺少更高级别的功能,例如:

commute :: (Functor f, Monad m) => f (m a) -> m (f a)

我的问题是:我是否可以使用更通用的类型签名来编写 deMaybe,例如假设的 commute,承认我正在尝试将一个函子转换为另一个函子?可以使用 fmap>>=pure 等函数来完成吗?

您可以使用 sequence :: (Traversable t, Monad m) => t (m a) -> m (t a),但这需要 Traversable。对于 t ~ (b, )m ~ Maybe,这就是:

Prelude> sequence (2, Just 3)
Just (2,3)
Prelude> sequence (2, Nothing)
Nothing

A Traversable 是数据结构的类型类,可以转换为具有相同形状的项目。我们需要它来构造一个 2 元组(或列表,或类似的东西)。

或者我们可以使用 sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) as ,这更通用,因为所有 Monad 也是 Applicative

Prelude> sequenceA (2, Just 3)
Just (2,3)
Prelude> sequenceA (2, Nothing)
Nothing