Haskell 按名称调用和按值调用的区别在哪个阶段?

Haskell 按名称调用和按值调用的区别在哪个阶段?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,大多数其他语言使用按值调用。Haskell使用按名称调用(惰性评估),我想知道它是如何运行的,我认为它比按值调用更好 以问题为例, “重复”功能定义如下: repeat' :: a -> [a] repeat' x = x:repeat' x 使用repeat'3将获得一个无限的3个列表, ghci>重复'3将生成3个连续, 但是take 5(重复'3)只会得到[3,3,3,3] haskell如何知道以第五个递归内部repeat'函数结束?此外,我不认为这是采取行动的问题 当代码

大多数其他语言使用按值调用。Haskell使用按名称调用(惰性评估),我想知道它是如何运行的,我认为它比按值调用更好

以问题为例,
“重复”功能定义如下:

repeat' :: a -> [a]   
repeat' x = x:repeat' x
使用
repeat'3
将获得一个无限的3个列表,
ghci>重复'3
将生成3个连续,
但是
take 5(重复'3)
只会得到
[3,3,3,3]

haskell如何知道以第五个递归内部
repeat'
函数结束?此外,我不认为这是采取行动的问题


当代码执行到哪个阶段时,它与按值调用不同


谢谢

您将得到一个无限的3个列表,因为在交互式会话中键入
repeat'3
实际上调用了
show(repeat'3)
,并且
show
尝试迭代
repeat'3
的整个返回值<另一方面,code>take,只尝试从列表中获取有限数量的元素。以下是前奏曲中的定义:

take n _      | n <= 0 =  []
take _ []              =  []
take n (x:xs)          =  x : take (n-1) xs

取n | n简言之,总是减少最外层的表达式,它是可减少的:
头(重复3)
->
头(3:重复3)
->
3
。在第一种情况下,
head
是不可归约的,因为它必须在其参数上进行模式匹配,但其参数不是构造函数。但是,
repeat
不进行模式匹配,因此可以减少模式匹配。在第一次缩减之后,
head
现在可以缩减,因为有一个构造函数(the
)“当代码执行到哪个阶段时,它与按值调用不同?”呃。。。什么?你会问这样的问题吗:假设我们使用按值调用作为传递函数参数的策略,而不是按名称调用,这会有什么不同吗?我相信,按价值调用,你实际上意味着急切的减少,在这种情况下,代码>重复3 只是“代码>未定义的< /代码>,所以<代码>取5未定义的/未定义的< /代码>,程序将永远被卡住。”Bakuriu,你可以把名字叫做懒惰的评价(这将是更好的理解)。。当表达式可以进行求值时,将使用按值调用,当然,只要编译器可以,Haskell不使用按值调用。我不明白你说的repeat 3只是未定义的,它将在哪一点进行计算。大多数其他语言(如c/c++)都使用按值调用,我想知道Haskell如何处理未定义的
(repeat 3)?谢谢你的意思是说
take
在开始时将3视为空列表吗?但是当
take
尝试访问
repeat 3
时,表达式不会被计算?它从不将
(repeat'3)
视为空列表;相反,它在任何时间点都不会看头部以外的任何东西。未计算的尾部被传递给递归调用。此外,未计算的尾部在哪个点进行计算?