haskell - 作为 Monad 实例的函数

标签 haskell monads

我很难理解一个函数如何成为一个 monad。

根据 Control.Monad.Instances 中的声明,函数 (->) r 是一个 monad:

instance Monad ((->) r) where  
    return x = \_ -> x  
    h >>= f = \w -> f (h w) w  

甚至米兰·利波瓦卡 (Miran Lipovača) says这让我很困惑:

The implementation for >>= seems a bit cryptic, but it's really not all that. When we use >>= to feed a monadic value to a function, the result is always a monadic value. So in this case, when we feed a function to another function, the result is a function as well. That's why the result starts off as a lambda. All of the implementations of >>= so far always somehow isolated the result from the monadic value and then applied the function f to that result. The same thing happens here. To get the result from a function, we have to apply it to something, which is why we do (h w) here to get the result from the function and then we apply f to that. f returns a monadic value, which is a function in our case, so we apply it to w as well.

(>>=) 的类型签名是这样的: (>>=)::m a -> (a -> m b) -> m b

因此,我认为 h 的类型为 m af 的类型为 (a -> m b)。如果函数是 m a,它是否返回 a 类型值?或者它是否返回采用 a 类型的其他内容?

如果将 h 的非 monad 值输入到 f,那么我们得到: f(高宽) 看起来不错。由于 f 是一个函数并且采用了唯一的参数,因此它已经是一个值,不是吗?由于它是一个单子(monad)函数,因此该值也是一个单子(monad)值。那么为什么它需要另一个值w?将 w 提供给 f some 不会使其成为非单子(monad),即它不再是一个函数,不是吗?我也无法理解为什么 f Somethingh 采用相同的参数 w 并返回不同的值类型(m am b)。

最佳答案

首先,这是 (>>=) 的类型:

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

现在,将 m 专门用于 ((->) r):

(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b

用所有函数箭头中缀重写:

(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)

删除一些多余的括号:

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b

此时应该更容易看到发生了什么:将第三个参数(r 类型)赋予第一个参数以获取 a 类型的内容>,然后将该结果和第三个参数都赋予第二个参数,以获得 b 类型的最终结果。

因此,((->) r) 作为 Monad 表示该 monad 中每个值的额外函数参数,并且当 Monadic 值组合在一起时,单个“extra"参数被复制并赋予每个输入值。本质上,这为一元值创建了一个“只读全局环境”。此解释作为 Reader monad 明确提供,它只是 ((->) r) 的包装器。

关于haskell - 作为 Monad 实例的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13080014/

相关文章:

haskell - 为什么 Applicative 应该是 Monad 的父类(super class)?

algorithm - 如何让这段Haskell代码更简洁?

haskell - 具有 `put` 函数的状态 Monad

haskell - 在运行时选择一个 monad

scala - Scala 中的 Monad 变形金刚

haskell - 在 catamorphism 中组合 f-代数的规则是什么

haskell - 如何重启沙盒和自定义编译的 Xmonad

json - 是否可以使用 Text.JSON 在 haskell 中创建嵌套的 JSON 对象?

haskell - 将错误值提升到 ErrorT monad 转换器

haskell - 并行 haskell 。对生产者进行速率限制