简体   繁体   English

Haskell 中的单子

[英]Monads in Haskell

I'm new to Monads and was trying to write an add function and I'm unsure why this doesn't work.我是 Monads 的新手,正在尝试编写一个 add function,但我不确定为什么这不起作用。 When using monads, is there a specific way you need to return a value?使用 monad 时,是否需要特定的方法来返回值?

monadd :: (Monad m, Num b) => m b -> m b -> m b
monadd mx my = mx >>= (\x -> my >>= (\y -> (x + y)))

You want to use pure (more general form of return )你想使用pure (更一般的return形式)

monadd :: Monad m => Num a => m a -> m a -> m a
monadd mx my = mx >>= (\x -> my >>= (\y -> pure (x + y)))

The right-hand side (continuation) of >>= must always return a monadic action. >>=的右侧(延续)必须始终返回一个单子操作。 But when you add x + y:: a you have a number.但是当你添加x + y:: a你有一个数字。 You need pure (x + y):: ma to turn it into a monadic action:你需要pure (x + y):: ma把它变成一个 monadic 动作:

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

You can equivalently write it in do -notation您可以等效地用do符号编写它

monadd :: Monad m => Num a => m a -> m a -> m a
monadd mx my = do
  x <- mx
  y <- my
  pure (x + y)

Actually.实际上。 This doesn't require Monad .这不需要Monad Applicative (n-ary lifting) is sufficient: Applicative (n 元提升)就足够了:

monadd :: Applicative m => Num a => m a -> m a -> m a
monadd = liftA2 (+)

Reminder that Functor lifts a unary function and Applicative lifts constants and n-ary functions (where liftA0 = pure and liftF1 = fmap ):提醒Functor提升一元 function 和Applicative提升常量和 n 元函数(其中liftA0 = pureliftF1 = 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)

You only need Monad when there is a dependency between the computations.当计算之间存在依赖关系时,您只需要Monad Notice that in your case the my computation does not dependent on the result of the mx computation.请注意,在您的情况下, my计算不依赖于mx计算的结果。

If mb depended on the output of ma it would become a -> mb .如果mb依赖于ma的 output 它将变成a -> mb Then Monad is required:然后需要Monad

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)

When using monads, is there a specific way you need to Return a value?使用 monad 时,是否需要特定的方法来返回值?

Yes, you will need to wrap x and y back in a monadic context, with return:: Monad m => a -> ma , so:是的,您需要使用return:: Monad m => a -> maxy包装回 monadic 上下文中,因此:

monadd :: (Monad m, Num b) => m b -> m b -> m b
monadd mx my = mx >>= (\x -> my >>= return (x+y)))

Since the two operations of the monad mx and my operate independently of each other however, Applicative is sufficient, you can implement this as:由于 monad mxmy的两个操作相互独立,但是Applicative就足够了,您可以将其实现为:

monadd :: (Applicative f, Num b) => f b -> f b -> f b
monadd mx my = (+) <$> mx <*> my

or through liftA2:: Applicative f => (a -> b -> c) -> fa -> fb -> f c :或者通过liftA2:: Applicative f => (a -> b -> c) -> fa -> fb -> f c

monadd :: (Applicative f, Num b) => f b -> f b -> f b
monadd = liftA2 (+)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM