与Functor不同,Monad可以改变形状吗? [英] Unlike a Functor, a Monad can change shape?
问题描述
我总是喜欢以下关于monad相对于函数的权力的直观解释:monad可以改变形状;例如:长度$ fmap f [1,2,3]
总是等于 3
。
然而,对于monad,长度$ [1,2,3]> ;> = g
通常不会等于 3
。例如,如果 g
被定义为:
g ::数字a)=> a - > [a]
gx = if x == 2 then [] else [x]
然后 [1,2,3]>> = g
等于 [1,3]
p>
稍微麻烦我的是 g
的类型签名。看起来不可能定义一个函数来改变输入的形状,使用一般的monadic类型,例如:
h :: (Monad m,Num a)=> a - > ma
MonadPlus或MonadZero类型类具有相关的零元素,而不是 []
,但现在我们拥有比单子更多的东西。
我是否正确?如果是这样,是否有办法向Haskell的新手表达这种微妙之处。我想让我心爱的单身可以改变形状的短语,只是一个更诚实的接触;如果需要的话。
到一个仿函数:monad可以改变形状;一个仿函数不能。
顺便说一句,你在这里略微有些微妙。为了术语的缘故,我将Haskell意义上的 仅限于函数 Functor
分成三部分:参数部分由类型参数决定,由 fmap
,不变的部分,比如 State 中的元组构造函数,以及其他任何形式的shape,比如构造函数之间的选择,
的参数部分映射函数当然。 Nothing
与 Just
)或涉及其他类型参数的部分(例如, Reader
)。
Monad 可以根据参数值部分,它不仅仅是改变形状。复制列表中的每个元素或删除前五个元素将改变形状,但过滤列表需要检查元素。
这实际上是如何 Applicative
适合它们 - 它允许您独立组合两个 Functors
的形状和参数值,而不会影响前者。
我是否正确?如果是这样,是否有办法向Haskell的新手表达这种微妙之处。我想让我心爱的单身可以改变形状的短语,只是一个更诚实的接触;如果需要的话。
也许你在这里寻找的微妙之处在于你并没有真正改变任何东西。 Monad
中的任何内容都不会让您明确地弄乱形状。它可以让您根据每个参数值创建新形状,并将这些新形状重新组合为一个新的复合形状。
因此,您将永远受到限制通过可用的方式来创建形状。对于完全通用的 Monad
,您只需要 return
,通过定义可以创建任何形状,这样(>> = return)
是身份函数。定义一个 Monad
可以告诉你在给定某种功能的情况下你可以做什么;它不会为你提供这些功能。
I've always enjoyed the following intuitive explanation of a monad's power relative to a functor: a monad can change shape; a functor cannot.
For example: length $ fmap f [1,2,3]
always equals 3
.
With a monad, however, length $ [1,2,3] >>= g
will often not equal 3
. For example, if g
is defined as:
g :: (Num a) => a -> [a]
g x = if x==2 then [] else [x]
then [1,2,3] >>= g
is equal to [1,3]
.
The thing that troubles me slightly, is the type signature of g
. It seems impossible to define a function which changes the shape of the input, with a generic monadic type such as:
h :: (Monad m, Num a) => a -> m a
The MonadPlus or MonadZero type classes have relevant zero elements, to use instead of []
, but now we have something more than a monad.
Am I correct? If so, is there a way to express this subtlety to a newcomer to Haskell. I'd like to make my beloved "monads can change shape" phrase, just a touch more honest; if need be.
I've always enjoyed the following intuitive explanation of a monad's power relative to a functor: a monad can change shape; a functor cannot.
You're missing a bit of subtlety here, by the way. For the sake of terminology, I'll divide a Functor
in the Haskell sense into three parts: The parametric component determined by the type parameter and operated on by fmap
, the unchanging parts such as the tuple constructor in State
, and the "shape" as anything else, such as choices between constructors (e.g., Nothing
vs. Just
) or parts involving other type parameters (e.g., the environment in Reader
).
A Functor
alone is limited to mapping functions over the parametric portion, of course.
A Monad
can create new "shapes" based on the values of the parametric portion, which allows much more than just changing shapes. Duplicating every element in a list or dropping the first five elements would change the shape, but filtering a list requires inspecting the elements.
This is essentially how Applicative
fits between them--it allows you to combine the shapes and parametric values of two Functors
independently, without letting the latter influence the former.
Am I correct? If so, is there a way to express this subtlety to a newcomer to Haskell. I'd like to make my beloved "monads can change shape" phrase, just a touch more honest; if need be.
Perhaps the subtlety you're looking for here is that you're not really "changing" anything. Nothing in a Monad
lets you explicitly mess with the shape. What it lets you do is create new shapes based on each parametric value, and have those new shapes recombined into a new composite shape.
Thus, you'll always be limited by the available ways to create shapes. With a completely generic Monad
all you have is return
, which by definition creates whatever shape is necessary such that (>>= return)
is the identity function. The definition of a Monad
tells you what you can do, given certain kinds of functions; it doesn't provide those functions for you.
这篇关于与Functor不同,Monad可以改变形状吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!