使用列表 monad 进行迭代

发布于 2025-01-15 21:29:14 字数 569 浏览 4 评论 0原文

我无法理解列表 monad 的迭代行为如何从其定义导出。

instance Monad [] where
  m >>= f  = concatMap f m
  return x = [x]
  fail s   = []

我读过的讨论似乎忽略了 >>= 如何创建控制结构的问题,正如 do 表示法最清楚地显示的那样:

allEvenOdds :: Int -> [(Int,Int)]
allEvenOdds n = do
  evenValue <- [2,4 .. n]               
  oddValue <- [1,3 .. n]                
  return (evenValue,oddValue)

这是否内置于Haskell,我假设 IO monad 与实际 i/o 的接口的方式是?

I'm having trouble understanding how the iterative behavior of the list monad can be derived from its definition.

instance Monad [] where
  m >>= f  = concatMap f m
  return x = [x]
  fail s   = []

Discussions I've read seem to pass over the question of how >>= creates a control structure, as shown most clearly with do notation:

allEvenOdds :: Int -> [(Int,Int)]
allEvenOdds n = do
  evenValue <- [2,4 .. n]               
  oddValue <- [1,3 .. n]                
  return (evenValue,oddValue)

Is this built in to Haskell, the way I assume the IO monad's interface to actual i/o is?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心的憧憬 2025-01-22 21:29:14

没有任何内置内容,一切都是您引用的 Monad 实例的简单结果(并且,由于此示例使用 do 表示法,因此它如何脱糖以使用 >>=< /code> 运算符):

allEvenOdds n = do
  evenValue <- [2,4 .. n]               
  oddValue <- [1,3 .. n]                
  return (evenValue,oddValue)

-- desugaring the do notation
allEvenOdds n =
  [2,4 .. n] >>= \evenValue ->
  [1,3 .. n] >>= \oddValue ->
  return (evenValue, oddValue)

-- using the list instance of Monad to replace >>= and return
allEvenOdds n =
  concatMap (\evenValue ->
    concatMap (\oddValue -> [(evenvalue, oddValue)]) [1,3 .. n]
  ) [2,4 .. n]

您希望可以轻松地看到它“迭代”两个列表,并生成所有对(偶数、奇数)的列表,并从两个列表中获取值。

在较高的层次上,我们可以说列表 monad 导致迭代,因为 concatMapmap 一样,为列表的每个元素执行给定的函数,因此它隐式地执行迭代列表。

There's nothing built-in, everything is a simple consequence of the Monad instance you quoted (and, since this example uses do notation, how that desugars to uses of the >>= operator):

allEvenOdds n = do
  evenValue <- [2,4 .. n]               
  oddValue <- [1,3 .. n]                
  return (evenValue,oddValue)

-- desugaring the do notation
allEvenOdds n =
  [2,4 .. n] >>= \evenValue ->
  [1,3 .. n] >>= \oddValue ->
  return (evenValue, oddValue)

-- using the list instance of Monad to replace >>= and return
allEvenOdds n =
  concatMap (\evenValue ->
    concatMap (\oddValue -> [(evenvalue, oddValue)]) [1,3 .. n]
  ) [2,4 .. n]

which you can hopefully easily see "iterates over" both lists and results in a list of all pairs of (even, odd) with values taken from both lists.

At a high level, we can say that the list monad results in iteration simply because concatMap, like map, executes the given function for each element of the list, so it implicitly iterates over the list.

梦言归人 2025-01-22 21:29:14

Monad 类型类模型的列表实例非确定性:您可以将每个 var <- someList 视为 for像 Python 中一样循环。

do 表示法被脱糖为 [2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\ oddValue -> return (evenValue, oddValue))),因此这相当于 Python 中的内容,例如:

    result = []
    for evenValue in range(2, n, 2):
        for oddValue in range(1, n, 2):
            result.append((evenValue, oddValue))

或者使用列表理解:

    result = [
        (evenValue, oddValue)
        for evenValue in range(2, n, 2)
        for oddValue in range(1, n, 2)
    ]

这对于实例 Monad [] 有效,表达式 [2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue)) ) 因此等价于:

concatMap (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))) [2,4 .. n]

因此:

concatMap (\evenValue -> concatMap (\oddValue -> [(evenValue, oddValue)]) [1, 3 .. n]) [2,4 .. n]

但是 do 表示法并不是“硬连线”到 IOIO 只是一个实例的Monad 的实现方式是一个 IO 操作将在第二个操作之前运行。对于列表,它的实现方式与跨越 Python for 循环的方式相同。

The list instance of the Monad typeclass models nondeterminism: you can see each var <- someList as a for loop like in Python.

The do notation is desugared to [2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))), so this is equivalent to something in Python like:

    result = []
    for evenValue in range(2, n, 2):
        for oddValue in range(1, n, 2):
            result.append((evenValue, oddValue))

or with list comprehension:

    result = [
        (evenValue, oddValue)
        for evenValue in range(2, n, 2)
        for oddValue in range(1, n, 2)
    ]

This works since for instance Monad [], the expression [2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))) is thus equivalent to:

concatMap (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))) [2,4 .. n]

and thus:

concatMap (\evenValue -> concatMap (\oddValue -> [(evenValue, oddValue)]) [1, 3 .. n]) [2,4 .. n]

But do notation is not "hardwired" to IO: IO is just an instance of Monad that is implemented in such way that one IO action will run before the second one. For lists, it thus is implemented in an equivalent way as spanning Python for loops.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文