Haskell Monad - 列表中的 Monad 如何工作? [英] Haskell Monad - How does Monad on list work?

查看:33
本文介绍了Haskell Monad - 列表中的 Monad 如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了理解 Monad,我想出了以下定义:

In order to understand Monad, I came up with the following definitions:

class Applicative' f where
 purea :: a -> f a
 app :: f (a->b) -> f a -> f b

class Applicative' m =>  Monadd m where
 (>>|) :: m a -> (a -> m b) -> m b

instance Applicative' [] where
 purea x = [x]
 app gs xs = [g x | g <- gs, x <- xs]

instance Monadd [] where
 (>>|) xs f = [ y | x <-xs, y <- f x]

它按预期工作:

(>>|) [1,2,3,4] (x->[(x+1)])
[2,3,4,5]

我不确定它是如何工作的.例如:

I am not sure how it is working though. For example:

[ y | y <- [[1],[2]]]
[[1],[2]]

应用 (x->([x+1])[1,2,3] 的每个列表元素如何得到 [2,3,4] 而不是 [[2],[3],[4]]

How does application (x->([x+1]) to each list element of [1,2,3] result in [2,3,4] and not [[2],[3],[4]]

或者很简单,我的困惑似乎源于不理解这个语句如何[ y |x <-xs, y <- f x] 实际有效

Or quite simply my confusion seems to stem from not understanding how this statement [ y | x <-xs, y <- f x] actually works

推荐答案

Wadler, Haskell 学院LYAHHaskellWiki, Quora 和更多描述列表 monad.

Wadler, School of Haskell, LYAH, HaskellWiki, Quora and many more describe the list monad.

比较:

  • (=<<) :: Monad m => (a -> m b) -> m a -> m b for lists with
  • concatMap :: (a -> [b]) -> [a] -> [b] for m = [].

常规的 (>>=) 绑定运算符翻转了参数,但在其他方面只是一个中缀 concatMap.

The regular (>>=) bind operator has the arguments flipped, but is otherwise just an infix concatMap.

或者很简单,我的困惑似乎源于不了解该语句的实际工作原理:

Or quite simply my confusion seems to stem from not understanding how this statement actually works:

(>>|) xs f = [ y | x <- xs, y <- f x ]

由于列表推导式等同于列表的 Monad 实例,所以这个定义有点像作弊.您基本上是在说某事物是 Monadd,就像它是 Monad 一样,因此您会遇到两个问题:理解列表推导式,以及仍然理解 Monad.

Since list comprehensions are equivalent to the Monad instance for lists, this definition is kind of cheating. You're basically saying that something is a Monadd in the way that it's a Monad, so you're left with two problems: Understanding list comprehensions, and still understanding Monad.

可以去除列表推导式以便更好地理解:

List comprehensions can be de-sugared for a better understanding:

就您而言,该语句可以用多种其他方式编写:

In your case, the statement could be written in a number of other ways:

  • 使用 do-notation:

  • Using do-notation:

(>>|) xs f = do x <- xs
                y <- f x
                return y

  • 去糖化为使用 (>>=) 操作符:

    (>>|) xs f = xs >>= x ->
                 f x >>= y ->
                 return y
    

  • 这可以缩短(每行重写一次):

  • This can be shortened (one rewrite per line):

      (>>|) xs f = xs >>= x -> f x >>= y -> return y -- eta-reduction
    ≡ (>>|) xs f = xs >>= x -> f x >>= return         -- monad identity
    ≡ (>>|) xs f = xs >>= x -> f x                    -- eta-reduction
    ≡ (>>|) xs f = xs >>= f                            -- prefix operator
    ≡ (>>|) xs f = (>>=) xs f                          -- point-free
    ≡ (>>|) = (>>=)
    

  • 因此,从使用列表推导式来看,您并没有真正声明一个新定义,您只是依赖于现有定义.如果您愿意,您可以改为定义您的 instance Monadd [] 而不依赖现有的 Monad 实例或列表推导式:

    So from using list comprehensions, you haven't really declared a new definition, you're just relying on the existing one. If you wanted, you could instead define your instance Monadd [] without relying on existing Monad instances or list comprehensions:

    • 使用concatMap:

    instance Monadd [] where
      (>>|) xs f = concatMap f xs
    

  • 再详细说明一下:

  • Spelling that out a little more:

    instance Monadd [] where
      (>>|) xs f = concat (map f xs)
    

  • 更详细地说明:

  • Spelling that out even more:

    instance Monadd [] where
      (>>|) [] f = []
      (>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
    

  • Monadd 类型类应该有类似于 return 的东西.我不知道为什么它不见了.

    The Monadd type class should have something similar to return. I'm not sure why it's missing.

    这篇关于Haskell Monad - 列表中的 Monad 如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆