首页 > 解决方案 > 让 cons 既具体又抽象地使用

问题描述

我在做这个

reverseP x = pour x []
  where pour []    ans = ans
        pour (h:t) ans = pour t (h:ans)

参数累加器比粗糙且昂贵的版本更好

reverse [] = []
reverse (h:t) = reverse t ++ [h]

但后来我想看看我是否可以reversePlet练习一样重做。我终于让这个工作了

reverseP2 x =
  let
    (t:ts) = x
    pour [] ans = ans
    pour (t:ts) ans = pour ts (t:ans)
  in pour x []

但我不知道它为什么起作用。期望继续用 Haskell 编写我不理解的工作代码是不现实的,所以我想我最好找出为什么会这样。让我感到困惑的是,我已经将传入分配x给了 cons (这被认为是一个元组吗?) (t:ts),但后来我(t:ts)以“抽象”的方式将其用作pour两行的参数。由于它有效,因此递归必须确实正确地分解了列表,即(t:ts)第一行中定义的缺点被正确地分解了。同样令人困惑的是let上面的表格如何允许pour以模式匹配的方式定义两次。我和守卫一起尝试过只保留一个pour,但后来(t:ts)没有正确分解——这也是我感到惊讶的部分原因。那么相同的缺点(t:ts)如何既具体又抽象,如何pourlet? 另外,可以reverseP2认为是尾递归吗?

标签: haskelllet

解决方案


难怪你对reverseP2. 模式匹配 onx是多余的,因为tts没有在let块中使用。块中使用的和t变量ts是(部分)函数定义中定义的更多局部变量。这些和具有相同名称的其他变量letpour (t:ts) anstts

事实上,模式匹配表达式(t:ts) = x是完全多余的。您可以简化reverseP2为:

reverseP2 x =
  let
    pour []     ans = ans
    pour (t:ts) ans = pour ts (t:ans)
  in pour x []

希望这更清楚地表明它只是使用另一种语法,但定义相同,如reverseP. 不是在函数定义的开头给出返回值,而是在in块中给出返回值let/in,而不是在节中定义辅助变量和函数,而是在where节中定义它们let


推荐阅读