[英]What is the 'minimum' needed to make an Applicative a Monad?
The Monad
typeclass can be defined in terms of return
and (>>=)
. Monad
类型类可以根据return
和(>>=)
。 However, if we already have a Functor
instance for some type constructor f
, then this definition is sort of 'more than we need' in that (>>=)
and return
could be used to implement fmap
so we're not making use of the Functor
instance we assumed.但是,如果我们已经有某个类型构造函数
f
的Functor
实例,那么这个定义有点“超出我们的需要”,因为(>>=)
并且return
可用于实现fmap
所以我们没有使用我们假设的Functor
实例。
In contrast, defining return
and join
seems like a more 'minimal'/less redundant way to make f
a Monad
.相比之下,定义
return
和join
似乎是使f
成为Monad
的更“最小”/更少冗余的方式。 This way, the Functor
constraint is essential because fmap
cannot be written in terms of these operations.这样,
Functor
约束是必不可少的,因为就这些操作而言, fmap
无法编写。 (Note join
is not necessarily the only minimal way to go from Functor
to Monad
: I think (>=>)
works as well.) (注意
join
不一定是从Functor
到Monad
的唯一最小方法:我认为(>=>)
也有效。)
Similarly, Applicative
can be defined in terms of pure
and (<*>)
, but this definition again does not take advantage of the Functor
constraint since these operations are enough to define fmap
.类似地,
Applicative
可以用pure
和(<*>)
定义,但是这个定义再次没有利用Functor
约束,因为这些操作足以定义fmap
。
However, Applicative f
can also be defined using unit :: f ()
and (>*<) :: fa -> fb -> f (a, b)
.但是,
Applicative f
也可以使用unit :: f ()
和(>*<) :: fa -> fb -> f (a, b)
。 These operations are not enough to define fmap
so I would say in some sense this is a more minimal way to go from Functor
to Applicative
.这些操作不足以定义
fmap
所以我会说从某种意义上说这是从Functor
到Applicative
一种更简单的方法。
Is there a characterization of Monad
as fmap
, unit
, (>*<)
, and some other operator which is minimal in that none of these functions can be derived from the others? Monad
是否有一个特征为fmap
、 unit
、 (>*<)
和其他一些最小的运算符,因为这些函数都不能从其他函数派生出来?
(>>=)
does not work, since it can implement a >*< b = a >>= (\\ x -> b >>= \\ y -> pure (x, y))
where pure x = fmap (const x) unit
. (>>=)
不起作用,因为它可以实现a >*< b = a >>= (\\ x -> b >>= \\ y -> pure (x, y))
其中pure x = fmap (const x) unit
。join
since m >>= k = join (fmap km)
so (>*<)
can be implemented as above.m >>= k = join (fmap km)
所以(>*<)
可以如上实现,也不会join
。(>=>)
fails similarly.(>=>)
同样失败。I have something, I think.我有东西,我想。 It's far from elegant, but maybe it's enough to get you unstuck, at least.
它远非优雅,但至少足以让你摆脱困境。 I started with
join :: m (ma) -> ???
我从
join :: m (ma) -> ???
and asked "what could it produce that would require (<*>)
to get back to ma
?", which I found a fruitful line of thought that probably has more spoils.并问“它会产生什么需要
(<*>)
才能回到ma
?”,我发现这是一个富有成效的思路,可能有更多的战利品。
If you introduce a new type T
which can only be constructed inside the monad:如果你引入一个只能在 monad 内部构造的新类型
T
:
t :: m T
Then you could define a join-like operation which requires such a T
:然后你可以定义一个类似连接的操作,它需要这样一个
T
:
joinT :: m (m a) -> m (T -> a)
The only way we can produce the T
we need to get to the sweet, sweet a
inside is by using t
, and then we have to combine that with the result of joinT
somehow.我们可以生产的唯一途径
T
,我们需要得到的甜,甜a
里面是用t
,然后我们要结合起来,与结果joinT
莫名其妙。 There are two basic operations that can combine two m
s into one: (<*>)
and joinT
-- fmap
is no help.有两个基本操作可以将两个
m
合并为一个: (<*>)
和joinT
-- fmap
没有帮助。 joinT
is not going to work, because we'll just need yet another T
to use its result, so (<*>)
is the only option, meaning that (<*>)
can't be defined in terms of joinT
. joinT
不会工作,因为我们只需要另一个T
来使用它的结果,所以(<*>)
是唯一的选项,这意味着(<*>)
不能根据joinT
定义。
You could roll that all up into an existential, if you prefer.如果您愿意,您可以将所有内容汇总为存在主义。
joinT :: (forall t. m t -> (m (m a) -> m (t -> a)) -> r) -> r
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.