gpt4 book ai didi

list - Haskell Tuple 在无限列表上的解构在将 Tuple 作为参数解构时与使用 let 解构时的行为不同

转载 作者:行者123 更新时间:2023-12-02 02:34:59 25 4
gpt4 key购买 nike

当尝试使用 foldr 实现 dropWhile 时,我想出的第一个算法是

dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur (acc, xs) ->
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])


虽然这有效,但它会导致无限列表上的堆栈溢出而不给出任何值。
因为我不确定,为什么这不起作用,我只是玩弄了这个功能,直到我想出了这个:
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur t -> let (acc, xs) = t in
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])

如您所见,这个和第一个之间的唯一区别是,我在这里解构元组 (acc, xs)在 let 绑定(bind)中,而不是直接在函数参数内部进行解构。由于某些奇怪的原因,此代码适用于无限列表。
如果有人知道为什么会这样,请告诉我。

最佳答案

Haskell 中的 Let 表达式是惰性的:

Let Expressions

(...) Pattern bindings are matched lazily; an implicit ~ makes these patterns irrefutable.



相比之下,lambda 抽象去糖为 case ,从而使构造函数模式变得严格:

Curried applications and lambda abstractions

Translation: The following identity holds:

\ p1 … pn -> e = \ x1 … xn -> case (x1, …, xn) of (p1, …, pn) -> e

关于list - Haskell Tuple 在无限列表上的解构在将 Tuple 作为参数解构时与使用 let 解构时的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62352950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com