我是Monads的新手,我想写一个add函数,但我不知道为什么这个函数不起作用。当使用Monads时,有没有一个特定的方法来返回一个值?
monadd :: (Monad m, Num b) => m b -> m b -> m b monadd mx my = mx >>= (\x -> my >>= (\y -> (x + y)))
zz2j4svz1#
您要使用pure(return的更一般形式)
pure
return
monadd :: Monad m => Num a => m a -> m a -> m a monadd mx my = mx >>= (\x -> my >>= (\y -> pure (x + y)))
>>=的右边(继续)必须总是返回一元动作,但是当你加上x + y :: a时,你得到一个数字,你需要pure (x + y) :: m a将它转换成一元动作:
>>=
x + y :: a
pure (x + y) :: m a
monadd :: Monad m => Num a => m a -> m a -> m a monadd mx my = mx >>= (\x -> my >>= (\y -> pure (x + y))) ^^^ ^ ^^^ ^ ^^^^^^^^^^^^ m a a m a a m a
可以等效地用do表示法来写它。
do
monadd :: Monad m => Num a => m a -> m a -> m a monadd mx my = do x <- mx y <- my pure (x + y)
实际上,这并不需要Monad。Applicative(n元提升)就足够了:
Monad
Applicative
monadd :: Applicative m => Num a => m a -> m a -> m a monadd = liftA2 (+)
提醒Functor提升一元函数,Applicative提升常量和n元函数(其中liftA0 = pure和liftF1 = fmap):
Functor
liftA0 = pure
liftF1 = fmap
liftA0 :: Applicative f => (a) -> (f a) liftF1 :: Functor f => (a -> b) -> (f a -> f b) liftA2 :: Applicative f => (a -> b -> c) -> (f a -> f b -> f c) liftA3 :: Applicative f => (a -> b -> c -> d) -> (f a -> f b -> f c -> f d)
只有当计算之间存在 * 依赖性 * 时,才需要Monad。注意,在您的示例中,my计算不依赖于mx计算的结果。如果m b依赖于m a的输出,它将变成a -> m b。那么Monad是必需的:
my
mx
m b
m a
a -> m b
dependency :: Monad m => (a -> b -> c) -> m a -> (a -> m b) -> m c dependency (·) as bs = do a <- as b <- bs a pure (a · b)
5sxhfpxr2#
当使用单子时,是否需要特定的方法来返回一个值?是的,您需要将x和y Package 回一元上下文中,使用**return :: Monad m => a -> m a**,因此:
x
y
return :: Monad m => a -> m a
monadd :: (Monad m, Num b) => m b -> m b -> m b monadd mx my = mx >>= (\x -> my >>= return (x+y)))
由于单子mx和my的两个操作彼此独立,因此Applicative就足够了,您可以将其实现为:
monadd :: (Applicative f, Num b) => f b -> f b -> f b monadd mx my = (+) <$> mx <*> my
或通过**liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c**:
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
monadd :: (Applicative f, Num b) => f b -> f b -> f b monadd = liftA2 (+)
2条答案
按热度按时间zz2j4svz1#
您要使用
pure
(return
的更一般形式)>>=
的右边(继续)必须总是返回一元动作,但是当你加上x + y :: a
时,你得到一个数字,你需要pure (x + y) :: m a
将它转换成一元动作:可以等效地用
do
表示法来写它。实际上,这并不需要
Monad
。Applicative
(n元提升)就足够了:提醒
Functor
提升一元函数,Applicative
提升常量和n元函数(其中liftA0 = pure
和liftF1 = fmap
):只有当计算之间存在 * 依赖性 * 时,才需要
Monad
。注意,在您的示例中,my
计算不依赖于mx
计算的结果。如果
m b
依赖于m a
的输出,它将变成a -> m b
。那么Monad
是必需的:5sxhfpxr2#
当使用单子时,是否需要特定的方法来返回一个值?
是的,您需要将
x
和y
Package 回一元上下文中,使用**return :: Monad m => a -> m a
**,因此:由于单子
mx
和my
的两个操作彼此独立,因此Applicative
就足够了,您可以将其实现为:或通过**
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
**: