且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Haskell Monad-列表中的Monad如何工作?

更新时间:2022-02-12 08:35:55

哈斯克尔学校 LYAH Quora 以及更多描述单子的列表.

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实例等效,因此此定义是一种作弊行为.基本上,您说的是某种东西,就像它是Monad一样,是Monadd,所以剩下两个问题:了解列表推导和仍然了解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:

  • 使用符号:

  • Using do-notation:

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

  • 建议使用(>>=)运算符:

  • De-sugared into using the (>>=) operator:

    (>>|) 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.