【发布时间】:2016-05-25 01:21:57
【问题描述】:
我是函数式编程的新手(来自 javascript),我很难区分两者之间的区别,这也混淆了我对函子与单子的理解。
函子:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Monad(简体):
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
-
fmap接受一个函数和一个函子,并返回一个函子。 -
>>=接受一个函数和一个 monad,然后返回一个 monad。
两者的区别在于函数参数:
-
fmap-(a -> b) -
>>=-(a -> m b)
>>= 接受一个返回 monad 的函数参数。我知道这很重要,但我很难看出这一点小事如何使单子比函子更强大。谁能解释一下?
【问题讨论】:
-
这在
(>>=)、(=<<)的翻转版本中更容易看出。对于(g <$>) :: f a -> f b,函数g :: a -> b对f“包装”没有影响——不会改变它。使用(k =<<) :: m a -> m b,函数k :: a -> m b本身创建新的m“包装”,所以它可以改变。 -
@WillNess 我可以“理解”这一点,但我看不到。我认为我遇到的真正问题是我看不到
>>=可以做到fmap无法做到的事情。在我的脑海中它们是等价的,因为我没有看到一个例子,这表明 fmap 是不够的。 -
使用列表,尝试从列表中过滤掉一些元素,使用
map。你不能。但是使用concatMap,您可以:map (\x->x+1) [1,2,3]vsconcatMap (\x-> [x,x+1|even x]) [1,2,3])。 -
@WillNess 好吧,我明白了!我一直认为
filter操作只是map的糖变体,但现在我意识到这根本不可能。 -
我们可以使用
map (\x -> [x|even x]) [1,2,3]编写几乎-filter,但它会产生[[],[2],[]],然后需要concat完成另一个级别的解释才能使其真正成为@ 987654350@.
标签: haskell functional-programming monads functor