haskell - 相互递归——有人可以帮助解释这段代码是如何工作的吗?

标签 haskell recursion

我正在阅读“A Gentle Introduction to Haskell”,并在早期使用了这个示例,该示例在 GHC 中运行良好,但在我的大脑中却很糟糕:

initial                 = 0
next resp               = resp
process req             = req+1

reqs                    = client initial resps
resps                   = server reqs

server          (req:reqs)   = process req : server reqs
client initial ~(resp:resps) = initial : client (next resp) resps

和调用代码:take 10 reqs
我怎么看,是reqs被调用,产生对 client 的调用参数为 0 和 resps .因此不会resps现在需要调用...它又调用 reqs再次?这一切似乎都是无限的......如果有人能详细说明它是如何工作的,我将不胜感激!

最佳答案

我发现手动计算小型 Haskell 程序的行为通常是值得的。评估规则非常简单。要记住的关键是 Haskell 是非严格的(也称为惰性):仅在需要时才计算表达式。懒惰是看似无限的定义可以产生有用结果的原因。在这种情况下,使用 take意味着我们只需要无限列表的前 10 个元素 reqs : 它们是我们“需要”的全部。

实际上,“需要”通常由模式匹配驱动。例如,列表表达式通常会被计算到我们可以区分 [] 的程度。和 (x:xs)在功能应用之前。 (请注意,在模式之前的“~”,就像在 client 的定义中一样,使它变得懒惰(或无可辩驳):在强制整个表达式之前,懒惰模式不会强制其参数。)

记住 take是:

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

评价take 10 reqs好像:
take 10 reqs 
      -- definition of reqs
    = take 10 (client initial resps)
      -- definition of client [Note: the pattern match is lazy]
    = take 10 (initial : (\ resp:resps' -> client (next resp) resps') 
                             resps)
      -- definition of take
    = initial : take 9 ((\ resp:resps' -> client (next resp) resps') 
                            resps)
      -- definition of initial
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      resps)
      -- definition of resps
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server reqs))
      -- definition of reqs
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server (client initial resps)))
      -- definition of client
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server (initial : {- elided... -}))
      -- definition of server
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (process initial : server {-...-}))
      -- beta reduction 
    = 0 : take 9 (client (next (process initial)) (server {-...-})
      -- definition of client 
    = 0 : take 9 (next (process initial) : {-...-})
      -- definition of take 
    = 0 : next (process initial) : take 8 {-...-}
      -- definition of next 
    = 0 : process initial : take 8 {-...-}
      -- definition of process 
    = 0 : initial+1 : take 8 {-...-}
      -- definition of initial 
    = 0 : 1 : take 8 {-...-}
      -- and so on...

关于haskell - 相互递归——有人可以帮助解释这段代码是如何工作的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/397341/

相关文章:

haskell - 为什么函数 (+) 匹配类型 (a -> b -> b)?

list - 让 Haskell 中的递归

haskell - 为什么我不能在记录更新符号中使用函数参数?

haskell - haskell 中的 minBound 和 MaxBound

haskell - 如何处理一个 IO (Maybe (IO (Maybe t))) 类型?

python - 递归地按键对嵌套的 OrderedDict 进行排序

java - 求三角形中的最大和

带有递归的 C# 类

java - 尾递归 - Java

haskell - 与 Word8 和 Int 相关的类型错误