monad 不保证 layered/non-layered monadic 值对 non-layered/non-monadic 函数的适用性,这是 good/bad 的事情吗?

Do monads not guarantee the applicability of layered/non-layered monadic values to non-layered/non-monadic functions, and is this a good/bad thing?

我只是想得到 monad,如果我问的问题不好,请多多包涵,但是...

如果单子只需要:

...这不是说:

这通常不会引起问题吗?

这不是说一旦我把一个类型变成了M y,我就不能使用任何(x -> y)的功能了吗? 或者,我可以假设我可以(M x -> (x -> y) -> (y -> M y) -> M y)吗?

再者,我们平时编程的时候不就是要提取原始类型吗?在某些东西之间切换时,比如 async a -> amaybe a -> a... 这不是一个常见的操作吗?我绝对可以看到有人想要优化 monad 的情况,如果他们认为它可以忽略不计(例如,日志记录 monad)。

另外,没有扁平化的分层单子呢?我知道列表可以被视为单子,其中限制扁平化是一个明确且合乎逻辑的选择,但是 async (async a) 单子值的假设情况又如何呢? async 没有扁平化功能? bind是不是只隐含了一层"monadic reduction",我们经常可以假设(M a -> (a -> M a) -> M a)经常可以看成是(M a -> (M a -> a) -> (a -> M a) -> M a),而(M M a -> (a -> M a) -> M a or M M a)不一定行得通?展平和非展平 monad 之间真的有区别吗?

Won't this usually cause a problem?

你可能会说这是"by design"。一种可能的用途是 IO;一旦你的值被 IO 污染,你就必须 "bubble up";您无法隐藏一个函数在纯值下执行 IO 的事实。


wouldn't that mean I either have to manually convert each (a -> b) -> (a -> M b) by applying a monadic constructor somewhere?

这比你想象的要容易,因为每个 Monad 也是一个 Functor 和一个 Applicative Functor:

randomDice :: IO Int
randomDice = randomRIO (1,6)

cheat :: Int -> Int
cheat = (+1)

main = do
    dice <- randomDice
    dice' <- cheat <$> randomDice

拥有所有 fmap<$>liftA/liftMpure/return 机制,这使得在 monadic 中轻松使用纯函数变得非常简单上下文。


(M (M a) -> M a) is not implicitly required

那个是假的。你只需要绑定即可实现它。

join              :: (Monad m) => m (m a) -> m a
join x            =  x >>= id