问题描述
我大致熟悉和。我也明白,它们可以用来解决类似的问题。
然而,我仍然有点困惑如何选择哪一个用于任何给定的情况。
何时使用monads,何时应该使用箭头?
要理解的最重要的事情是有更多的东西是箭头,而不是单子的东西。相反,monads比箭头严格得多(详细说明了哪种方式)。特别是,monad是装备有类型的应用函数(a〜> b,a)〜>的应用程序的箭头。 b
,其中(〜>)
是给定箭头的构造函数。 Lindley等人指出这破坏了术语和命令之间的细致区别箭头(或者,如果您愿意的话,对象和态射)。
应用函子具有各种各样的应用程序,特别是对于那些在流媒体上被认为是最好的操作。实际上,人们可以将箭头想象为通过在流上概括变换器的概念(即在给定应用函数构造的对象上引入态射的新语言)。根据我的经验,因为monads模糊了对象和态射之间的区别(也就是说,如果我正确地使用了这些词汇,会产生一个闭合的笛卡尔类别),那么,单子中的术语通常远比箭头或应用函子中的术语更不透明(尽管注意两者都允许您通过和)。
因此,如果给定monad的特性(即使它在概念上构成了monad的特性) ,那么它有可能开放更多的检查和优化。它也可能更容易序列化。因此,在解析器和电路建模中使用应用程序和箭头。
上面的尝试是一般的和描述性的。以下是我的一些自以为是的经验法则。
如果您需要建模看起来像状态的东西,请从monad开始。如果您需要建模看起来像全局控制流(即异常,延续)的东西,请从monad开始。如果出现与monad的权力和普遍性(即,对于哪个连接(join :: m(ma) - > ma)
)功能过于强大的要求冲突,则如果你需要模拟数据流和数据流转换,特别是某些特性的数据流(尤其是无限的过去和未来的观点)应该是不透明的,然后从一个适用的函子开始。如果你需要更强的关于流转换性质的推理,那就考虑伸手去找箭。
或者,粗略地说,应用是用于电路,箭头是用于电路的结构,单子用于通用计算效果。
当然,这个故事更多。有关应用程序,请参阅。有关箭头,请参阅,,,Hudak和Liu的经典论文等。对于monad来说,无处不在。当然,请注意,仅仅因为某物是单子,并不意味着应用符号可能不会更清晰和更具表现力。
I'm broadly familiar with the concepts of monads and arrows as used in functional programming. I also understand that they can be used to solve similar kinds of problems.
However, I'm still a bit confused about how to select which one to use in any given situation.
When should I use monads and when should I use arrows?
There are two excellent papers by Lindley, Wadler & Yallop (discussed at LTU here).
The most important thing to understand is that there are more things which are arrows than there are things which are monads. Conversely, monads are strictly more powerful than arrows (the second paper above specifies precisely in which fashion).
In particular, monads are arrows equipped with an apply function of type (a ~> b, a) ~> b
, where (~>)
is the constructor for a given arrow. Lindley et al. point out that this destroys the meticulous distinction arrows maintain between terms and commands (or, if you prefer, objects and morphisms).
Applicative functors have a wide variety of applications, particularly for things which are best thought of as operations on streams. One can in fact think of arrows as arising from generalizing the notion of a transformer on streams (i.e. introducing a new language for morphisms on objects constructed by a given applicative functor).
In my experience, because monads blur the distinction between objects and morphisms (i.e., if I'm using the words correctly, give rise to a closed cartesian category), then a term in a monad is generally far more necessarily opaque than a term in an arrow or applicative functor (although note that both let you inject arbitrary functions by the arr
and pure
methods respectively).
So if something is not given the characteristics of a monad (even though conceptually it forms one), then it is potentially open to greater inspection and optimization. It is also potentially easier to serialize. Hence the use of applicatives and arrows in parsers and circuit modeling.
The above attempted to be general and descriptive. Below are some of my opinionated rules of thumb.
If you need to model something that looks like state, start with a monad. If you need to model something that looks like global control flow (i.e. exceptions, continuations), start with a monad. If a requirement arises that conflicts with the power and generality of monads (i.e. for which join (join :: m (m a) -> m a)
is too powerful), then consider chipping away at the power of the thing you're using.
If you need to model streams, and transformations on streams, and particularly streams for which certain characteristics (particularly unlimited views of the past and future) should be opaque, then start with an applicative functor. If you need stronger reasoning about properties of transformations on streams, then think about reaching for an arrow.
Or, very crudely put, applicatives are for the actions of circuits, arrows are for the structures of circuits, and monads are for general-purpose computational effects.
There's of course much more to the story. For applicatives, see Conal Elliott's work on FRP in particular. For arrows, see the HXT XML parser library, the Yampa FRP project, the Haskell on a Horse web framework, Hudak and Liu's classic "Plugging a Space Leak with an Arrow" paper, among other things. For monads, see everywhere. And of course take note that just because something is a monad, that doesn't mean that applicative notation might not be clearer and more expressive.
这篇关于Monads与箭头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!