我是否使用合理的等式推理来根据foldr 定义过滤器?

发布于 2024-08-20 08:09:05 字数 1989 浏览 1 评论 0原文

好吧,这是使用foldr的过滤器函数的定义:

myFilter p xs = foldr step [] xs
    where step x ys | p x       = x : ys
                    | otherwise = ys

所以举例来说,假设我有这个函数:

myFilter odd [1,2,3,4]

所以它将是:

foldr step [] [1,2,3,4]

这将是

step 1 (foldr step [] [2,3,4])

,这将是

step 1 (step 2 (foldr step [] [3,4]))

,这将是

step 1 (step 2 (step 3 (foldr step [] [4])))

,这将是

step 1 (step 2 (step 3 (step 4 (foldr step [] []))))

和foldr步骤[] [] 是 [] 所以:

step 1 (step 2 (step 3 (step 4 [])))

现在我们将真正进入 step 函数。
这是 myFilter 函数中 step 的定义,来自上面:

step x ys | p x       = x : ys
          | otherwise = ys

另外,我提醒你,p 实际上是 odd<我们示例中的 /code> 函数。

好吧,我们又在这里:

step 1 (step 2 (step 3 (step 4 [])))

并且

x = 4 在最里面的 step 中,并且 4 并不奇怪,所以我们返回 < code>ys,即 []

所以现在我们得到:

step 1 (step 2 (step 3 []))

现在,在最里面的 step 中,x = 3 ,而 3 是奇数,因此我们返回 x:ys,即 3 : [],即 [3]< /code>,现在我们得到:

step 1 (step 2 [3])

现在,在内部步骤中,x = 2,并且2并不奇怪,所以我们返回 ys,即 [3],所以现在我们将得到:

step 1 [3]

现在,x = 11< /code> 是奇数,因此我们返回 x : ys,即 1 : [3],即 [1,3]

结束:-)。

我的所有举动都正确吗?
多谢 :-)。

ps myFilter 的定义来自于Real World Haskell,第 4 章。

well, this is the definition of the filter function using foldr:

myFilter p xs = foldr step [] xs
    where step x ys | p x       = x : ys
                    | otherwise = ys

so for example let's say i have this function:

myFilter odd [1,2,3,4]

so it will be:

foldr step [] [1,2,3,4]

and this will be

step 1 (foldr step [] [2,3,4])

and this will be

step 1 (step 2 (foldr step [] [3,4]))

and this will be

step 1 (step 2 (step 3 (foldr step [] [4])))

and this will be

step 1 (step 2 (step 3 (step 4 (foldr step [] []))))

and foldr step [] [] is [] so:

step 1 (step 2 (step 3 (step 4 [])))

now we will actually get into the step function.
here is the definition of step inside the myFilter function, from above:

step x ys | p x       = x : ys
          | otherwise = ys

also, i remind you that p is actually the odd function in our example.

well, again, we are here:

step 1 (step 2 (step 3 (step 4 [])))

and

x = 4 in the most inner step, and 4 isn't odd, so we returning ys, which is []

so now we get this:

step 1 (step 2 (step 3 []))

now, in the most inner step, x = 3, and 3 is odd, so we return x:ys, which is 3 : [], which is [3], and now we get:

step 1 (step 2 [3])

and now, in the inner step, x = 2, and 2 isn't odd, so we return ys, which is [3], so now we will get:

step 1 [3]

and now, x = 1, and 1 is odd, so we return x : ys, which is 1 : [3], which is [1,3].

The End :-).

am i right in all my moves?
thanks a lot :-).

p.s. the definition of myFilter is from the book Real World Haskell, in chapter 4.

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

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

发布评论

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

评论(3

梓梦 2024-08-27 08:09:05

第一次读时,我觉得这很正确。

但要记住的重要一点是,为了实现惰性求值,Haskell 实际上会以另一种方式看待事物。换句话说,真正的序列更像

step 1 (step 2 (step 3 (step 4 [])))

step 1 <block1>

变成,

[1, <block1>]

然后如果你尝试从该列表中提取下一个元素,它将评估

[1, step 2 <block2>]

哪个成为

[1, <block2>]

,然后尝试评估

[1, step 3 (step 4 [])]

变成

[1, step 3 <block3>]

哪个成为

[1, 3, <block3>]

等等。这花了我一段时间才能理解。对我来说,这是违反直觉的,因为 foldr 似乎是从“内向外”评估的,但 foldl 是从“由外向内”评估的,所以 foldr > 会是惰性的(确实如此),而 foldl 是严格的。但如果你按照我上面概述的方式思考它,那就有道理了(无论如何对我来说)。

This looks right to me on first read.

The important thing to remember though is that in order to achieve lazy evaluation, Haskell will actually look at things the other way. In other words, the real sequence is more like

step 1 (step 2 (step 3 (step 4 [])))

becomes

step 1 <block1>

which becomes

[1, <block1>]

then if you try to pull the next element from that list, it will evaluate

[1, step 2 <block2>]

which becomes

[1, <block2>]

and then trying to evaluate

[1, step 3 (step 4 [])]

turns into

[1, step 3 <block3>]

which becomes

[1, 3, <block3>]

etc. This took me a while to understand. It was counterintuitive to me that since foldr seems to be evaluated from the "inside out" but foldl is evaluated from the "outside in" that foldr would be lazy (which it is), whereas foldl is strict. But if you think of it the way I outlined above, it makes sense (to me, anyway).

凶凌 2024-08-27 08:09:05

只是为了扩展惰性计算顺序:基本上 Haskell 总是首先计算函数,直到必要时才查看参数。

如果使用 myFilter 调用的结果(例如打印),则将按以下顺序计算该函数:

myFilter odd [1,2,3,4]

首先计算 myFilter 函数:

foldr step [] [1,2,3,4]

现在 foldr 是最外面的函数并被求值:

step 1 (foldr step [] [2,3,4])

现在 step 被求值,生成 1,因为 1 是奇数:

1 : foldr step [] [2,3,4]

现在结果列表的第一个元素可用并且可由调用函数使用。如果调用函数还使用以下元素,则评估继续
使用 foldr

1 : step 2 (foldr step [] [3,4])

step 的评估现在不会产生任何新元素,因为 2 是偶数:

1 : foldr step [] [3,4]

所以再次 foldr

1 : step 3 (foldr step [] [4])

现在评估 < code>step 产生 3

1 : 3 : foldr step [] [4]

评估 foldr

1 : 3 : step 4 (foldr step [] [])

再次step

1 : 3 : foldr step [] []

最后foldr计算结果为空列表:

1 : 3 : []

Just to expand on the lazy evaluation order: Basically Haskell always evaluates the function first, not looking at the arguments until it has to.

If the result of the call to myFilter is used (for example printed), the function will be evaluated in the following order:

myFilter odd [1,2,3,4]

First the myFilter function is evaluated:

foldr step [] [1,2,3,4]

Now foldr is the outermost function and gets evaluated:

step 1 (foldr step [] [2,3,4])

Now step gets evaluated producing a 1, since 1 is odd:

1 : foldr step [] [2,3,4]

Now the first element of the result list is available and can be used by the calling function. If the calling function also uses the following elements evaluation continues
with the foldr:

1 : step 2 (foldr step [] [3,4])

The evaluation of step now doesn't produce any new elements, since 2 is even:

1 : foldr step [] [3,4]

So foldr again:

1 : step 3 (foldr step [] [4])

Now evaluating step produces 3:

1 : 3 : foldr step [] [4]

Evaluating foldr;

1 : 3 : step 4 (foldr step [] [])

And step once more:

1 : 3 : foldr step [] []

Finally foldr evaluates to an empty list:

1 : 3 : []
半步萧音过轻尘 2024-08-27 08:09:05

乍一看,您在特定示例中采取的步骤单独看来是正确的。但是,我想指出 filterfoldr 都可以有效地应用于无限列表 - 这应该表明顺序就 Haskell 而言,你的步骤是不正确的。

At first glance, the steps you've taken in your specific example look correct individually. However, I'd like to point out that both filter and foldr can be usefully applied to infinite lists--which should indicate that the order of your steps is incorrect as far as Haskell is concerned.

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