我是否使用合理的等式推理来根据foldr 定义过滤器?
好吧,这是使用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 = 1
和 1< /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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
第一次读时,我觉得这很正确。
但要记住的重要一点是,为了实现惰性求值,Haskell 实际上会以另一种方式看待事物。换句话说,真正的序列更像
是
变成,
然后如果你尝试从该列表中提取下一个元素,它将评估
哪个成为
,然后尝试评估
变成
哪个成为
等等。这花了我一段时间才能理解。对我来说,这是违反直觉的,因为
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
becomes
which becomes
then if you try to pull the next element from that list, it will evaluate
which becomes
and then trying to evaluate
turns into
which becomes
etc. This took me a while to understand. It was counterintuitive to me that since
foldr
seems to be evaluated from the "inside out" butfoldl
is evaluated from the "outside in" thatfoldr
would be lazy (which it is), whereasfoldl
is strict. But if you think of it the way I outlined above, it makes sense (to me, anyway).只是为了扩展惰性计算顺序:基本上 Haskell 总是首先计算函数,直到必要时才查看参数。
如果使用
myFilter
调用的结果(例如打印),则将按以下顺序计算该函数:首先计算
myFilter
函数:现在
foldr
是最外面的函数并被求值:现在
step
被求值,生成1
,因为1
是奇数:现在结果列表的第一个元素可用并且可由调用函数使用。如果调用函数还使用以下元素,则评估继续
使用
foldr
:对
step
的评估现在不会产生任何新元素,因为 2 是偶数:所以再次
foldr
:现在评估 < code>step 产生
3
:评估
foldr
;再次
step
:最后
foldr
计算结果为空列表: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:First the
myFilter
function is evaluated:Now
foldr
is the outermost function and gets evaluated:Now
step
gets evaluated producing a1
, since1
is odd: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
:The evaluation of
step
now doesn't produce any new elements, since 2 is even:So
foldr
again:Now evaluating
step
produces3
:Evaluating
foldr
;And
step
once more:Finally
foldr
evaluates to an empty list:乍一看,您在特定示例中采取的步骤单独看来是正确的。但是,我想指出
filter
和foldr
都可以有效地应用于无限列表 - 这应该表明顺序就 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
andfoldr
can be usefully applied to infinite lists--which should indicate that the order of your steps is incorrect as far as Haskell is concerned.