monad不能保证分层/非分层monadic值适用于非分层/非monadic函数,这是好事还是坏事?

时间:2016-01-08 06:45:13

标签: monads

我只是试图获得monad,所以如果我问一个糟糕的问题请耐心等待,但是...

如果monad只需要:

  • (a -> M a),其中M是monadic类型构造函数,
  • (M a -> (a -> M b) -> M b),这是绑定操作(我理解为将monad映射到非monadic到monadic值函数)

......并不意味着:

  • (M a -> a)
  • (M (M a) -> M a)不是含蓄要求的吗?

不会这通常会导致问题吗?

  • 假设我们有一组函数S,它们都具有类型(x -> y),其中x和y是任意类型。

  • 现在,假设我使用一组monadic函数M编程,其类型为x -> M y

这是否意味着一旦我将类型转换为M y,我就无法使用任何(x -> y)函数? 或者,我可以假设我可以(M x -> (x -> y) -> (y -> M y) -> M y)吗?

此外,我们通常不想在编程时提取原始类型?在某些内容之间切换时,例如async a -> amaybe a -> a ...是不是常见的操作?我可以肯定地看到有人想要优化monad的情况,如果他们认为monad可以忽略不计(例如伐木monad)。

另外,没有展平的分层单子怎么办?我理解列表可以看作monad,其中限制扁平化是一个明确而合理的选择,但是async (async a) monadic值的假设情况呢async没有扁平函数?绑定只意味着一层" 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之间是否存在真正的区别?

1 个答案:

答案 0 :(得分:1)

  

不会这通常会导致问题吗?

你可能会说这是"设计"。其中一种可能的用途是IO;一旦你有一个被IO污染的价值,你必须"冒泡&#34 ;;你无法隐藏函数在纯值下执行IO的事实。

  

这并不意味着我要么必须手动转换每个(a - > b) - > (a - > M b)通过在某处应用monadic构造函数?

这比你想象的要容易,因为每个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)并非隐式要求

那个是假的。你只需要bind来实现它。

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