I am having difficulty understanding how a function can be a monad.
Function (->) r is a monad according to a declaration in Control.Monad.Instances:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
Run Code Online (Sandbox Code Playgroud)
Even what Miran Lipovača says about it makes me confused:
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.
The type signature of (>>=) is this: (>>=) :: m a -> (a -> m b) -> m b
So I take that h is typed as m a and f as (a -> m b). If a function is m a, does it return an a type value? or does it return something else taking an a type?
如果非monad值h被馈送f,那么我们得到:f(hw)看起来很好.既然f是一个功能并且已经采取了它的唯一论据,它已经是一个价值,不是吗?由于它是一个monadic函数,因此该值也是monadic值.为什么它需要另一个价值w?不摄食w,以f something使其成为非一元,即它不是一个功能更多,不是吗?我也无法理解为什么f something并h采用相同的参数w并返回不同的值类型(m a和m b).
C. *_*ann 11
首先,这是以下类型(>>=):
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
现在,m专门用于((->) r):
(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b
Run Code Online (Sandbox Code Playgroud)
用所有函数箭头中缀重写:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)
Run Code Online (Sandbox Code Playgroud)
删除一些多余的括号:
(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b
Run Code Online (Sandbox Code Playgroud)
在这一点上,应该更容易看到发生了什么:第三个参数(类型r)被赋予第一个获得类型的参数a,然后结果和第三个参数都被赋予第二个参数以获得一个类型的最终结果b.
因此,((->) r)a Monad表示该monad中每个值的额外函数参数,并且当monadic值组合时,单个"extra"参数被复制并赋予每个输入值.从本质上讲,这为monadic值创建了一个"只读全局环境".这种解释明确地作为Readermonad提供,它只是一个包装器((->) r).
通过查看是什么来理解这个monad可能更容易join,因为monad可以等效地使用fmap而join不是使用而不是>>=.
一般形式join具有类型Monad m => m (m b) -> m b,因此它需要一个"两层"monadic值并将其压缩到一层.
随着功能的单子,m ~ (a ->),所以join有型(a -> a -> b) -> (a -> b),因此需要两个参数的函数,并返回一个函数,只需要一个.
join :: (a -> a -> b) -> (a -> b)
join f = \x -> f x x
Run Code Online (Sandbox Code Playgroud)
如您所见,它只是重复了这个论点.
同样,fmap函数只是函数组成,而且return是const.
我认为理解这种方式要比理解更容易>>=.