gpt4 book ai didi

haskell - Haskell 中的函数是否总是评估其返回值?

转载 作者:行者123 更新时间:2023-12-03 15:12:17 24 4
gpt4 key购买 nike

我试图更好地理解 Haskell 的惰性,例如当它评估函数的参数时。

从此source :

But when a call to const is evaluated (that’s the situation we are interested in, here, after all), its return value is evaluated too ... This is a good general principle: a function obviously is strict in its return value, because when a function application needs to be evaluated, it needs to evaluate, in the body of the function, what gets returned. Starting from there, you can know what must be evaluated by looking at what the return value depends on invariably. Your function will be strict in these arguments, and lazy in the others.



那么 Haskell 中的函数总是评估自己的返回值吗?如果我有:
foo :: Num a => [a] -> [a]
foo [] = []
foo (_:xs) = map (* 2) xs

head (foo [1..]) -- = 4

根据以上段落, map (* 2) xs , 必须评估。直觉上,我认为这意味着应用 map到整个列表 - 导致无限循环。
但是,我可以成功地拿下结果。我知道 :在 Haskell 中是懒惰的,所以这是否意味着评估 map (* 2) xs只是意味着构建其他尚未完全评估的东西?

评估应用于无限列表的函数意味着什么?如果函数的返回值总是在函数被求值时被求值,那么函数真的可以返回一个 thunk 吗?

编辑:
bar x y = x
var = bar (product [1..]) 1

此代码不会挂起。当我创建 var ,它不评估它的 body 吗?还是设置 barproduct [1..]而不是评估?如果是后者, bar不是在 WHNF 中返回它的 body ,对,所以它真的“评估”了 x 吗?怎么可能 bar严于 x如果它不挂起计算 product [1..] ?

最佳答案

首先,Haskell 没有指定评估发生的时间,所以这个问题只能针对具体的实现给出明确的答案。

以下对于我所知道的所有非并行实现都是正确的,例如 ghc、hbc、nhc、huggs 等(所有基于 G 机器,顺便说一句)。

顺便说一句,要记住的是,当您听到 Haskell 的“评估”时,它通常意味着“评估到 WHNF”。

与严格的语言不同,您必须区分函数的两个“调用者”,第一个是在词法上发生调用的地方,第二个是需要值的地方。对于严格的语言,这两者总是一致的,但对于惰性语言则不然。
让我们举个例子,让它复杂一点:

foo [] = []
foo (_:xs) = map (* 2) xs

bar x = (foo [1..], x)

main = print (head (fst (bar 42)))
foo函数出现在 bar .评估 bar将返回一对,该对的第一个组件是对应于 foo [1..] 的 thunk .所以 bar是严格语言的调用者,但在惰性语言的情况下,它不会调用 foo根本,它只是建立了闭包。

现在,在 main函数我们实际上需要 head (fst (bar 42)) 的值因为我们必须打印它。所以 head函数实际上会被调用。 head函数是由模式匹配定义的,所以它需要参数的值。所以 fst叫做。它也是由模式匹配定义的并且需要它的参数所以 bar被调用, bar将返回一对, fst将评估并返回其第一个组件。现在终于 foo叫做”;并且通过调用我的意思是评估thunk(输入,因为它有时在TIM术语中被称为),因为需要该值。 foo 的实际代码的唯一原因被称为是我们想要一个值。所以 foo最好返回一个值(即 WHNF)。 foo函数将评估其参数并最终进入第二个分支。在这里,它将尾调用 map 的代码。 . map函数由模式匹配定义,它将评估其参数,这是一个缺点。所以 map 将返回以下 {(*2) y} : {map (*2) ys} , 我用过 {}表示正在构建的闭包。如您所见 map只返回一个 cons 单元格,头部是闭包,尾部是闭包。

为了更好地理解 Haskell 的操作语义,我建议你看一些描述如何将 Haskell 翻译成一些抽象机器的论文,比如 G 机器。

关于haskell - Haskell 中的函数是否总是评估其返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27685224/

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