[英]How to use function instance of reader monad?
I have found an interesting use of this monad:我发现了这个 monad 的一个有趣用法:
Prelude Control.Monad> liftM2 (,) head tail $ [1..5]
(1,[2,3,4,5])
It looks like useful technique that allows r
in (->) r
to be passed only once, where I would expect this expression to require duplicating the list first.它看起来是一种有用的技术,它允许
r
in (->) r
只传递一次,我希望这个表达式首先需要复制列表。
I don't quite understand how lifting actually works here.我不太明白这里的提升实际上是如何工作的。 Where is
>>=
or return
hidden? >>=
或return
隐藏在哪里? What are other common situations which would call for using this particular instance?需要使用此特定实例的其他常见情况是什么?
liftM2
takes a binary function and two monadic values and applies the function over the values inside the monad. liftM2
采用一个二元函数和两个liftM2
值,并将该函数应用于 monad 内的值。 Look at the implementation:看实现:
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do
x1 <- m1
x2 <- m2
return (f x1 x2)
Or if we desugar it we can see the explicit (>>=)
and return
:或者,如果我们对其进行脱糖,我们可以看到显式
(>>=)
并return
:
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 =
m1 >>= (\x1 ->
m2 >>= (\x2 ->
return (f x1 x2)))
This is useful whenever you have a need to apply a pure function inside a monad, the use cases are pretty wide since it's a very common task.当您需要在 monad 中应用纯函数时,这很有用,用例非常广泛,因为这是一项非常常见的任务。
(Read freyrs's answer first; this answer expands upon it.) (首先阅读freyrs 的回答;这个回答对此进行了扩展。)
See the defintion of the reader/Function monad instance查看reader/Function monad 实例的定义
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
You can see there where the input gets duplicated/forked ( r
appears twice on the right-hand-side of the \\ r
expression): Each value that is passed to (>>=)
(both head
and tail
, in your example) is then passed the same argument ( [1,..5]
) when the combined (monadic) function is applied to that argument.您可以在那里看到输入被复制/分叉的位置(
r
在\\ r
表达式的右侧出现两次):传递给(>>=)
每个值(>>=)
在您的示例中为head
和tail
)当组合(monadic)函数应用于该参数时[1,..5]
然后传递相同的参数( [1,..5]
)。
Without using monadic liftM2
, the (function application) expression (,) head tail
just creates a tuple (head, tail)
.不使用
liftM2
,(函数应用)表达式(,) head tail
只是创建一个元组(head, tail)
。 But when (as in liftM2
) monadic bind is applied instead of "plain" function application, those arguments are bound ("bind-ed") into the monadic value, where they remain "ready" to receive the bind result's function argument.但是当(如在
liftM2
)应用liftM2
bind而不是“普通”函数应用程序时,这些参数被绑定(“bind-ed”)到monadic值中,在那里它们保持“准备好”接收绑定结果的函数参数。
Note also that the final argument ( r = [1..5]
) is used once for each call to (>>=)
(which happens twice in liftM2
, that's what the 2
means).另请注意,最后一个参数 (
r = [1..5]
) 用于每次调用(>>=)
(在liftM2
中发生两次,这就是2
意思)。 The return
causes no additional use of the final argument, since in this monad we have return fr = const fr
( fr
added for explicitness), which ignores the argument r
. return
不会导致对最后一个参数的额外使用,因为在这个 monad 中我们有return fr = const fr
(为了明确而添加fr
),它忽略了参数r
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.