【问题标题】:Getting max value from a list in SML从 SML 中的列表中获取最大值
【发布时间】:2014-01-16 09:13:56
【问题描述】:

我目前正在学习 SML,我很难理解下面的代码

fun good_max (xs : int list) =
  if null xs
  then 0
  else if null (tl xs)
  then hd xs
  else
    (* for style, could also use a let-binding for (hd xs) *)
    let val tl_ans = good_max(tl xs)
    in
      if hd xs > tl_ans
      then hd xs
      else tl_ans
    end

hd xsinttl_ans 类型,我认为是 list 类型。 为什么这段代码有效?系统如何评估递归? 如果您可以使用 xs = [3, 4, 5] 向我展示它是如何工作的,那就太好了。

【问题讨论】:

  • ` let val y = old_max(tl[3,4,5]) in max(hd[3,4,5], y) end let val y = (let val y' = old_max (tl(tl[3,4,5))) in max(hd(tl[3,4,5],y')) end) in max(hd[3,4,5],y) let val y = (let val y' = old_max([5]) in max(4,y') end) in max(3,y) end let val y = 5 in max (3,y) 5`
  • 好的。我在尝试将代码放入评论框中时搞砸了。谢谢安德烈亚斯!我能够弄清楚您的工作原理并将其应用于我的代码。使用辅助函数使代码更优雅 :) 我的假设发生了错误,因为在评估函数之前我没有替换所有分支。递归确实是一个具有挑战性的话题。
  • FWIW,max 函数已作为 Int.max 存在于标准库中。此外,第三种情况的右侧显然可以简化为max(x, goodMax xs)——我没有这样做来演示let 中的缩减是如何工作的。最后,我建议宁愿在空的情况下抛出异常,因为结果 0 并不完全正确。总而言之,您可以将函数用折叠表示为简单的fun goodMax [] = raise Empty | goodMax(x::xs) = List.foldl Int.max x xs

标签: list recursion sml


【解决方案1】:

让我先将这段代码重写为等效但更易读的版本:

fun max(x,y) = if x > y then x else y

fun goodMax(nil) = 0
  | goodMax(x::nil) = x
  | goodMax(x::xs) = let val y = goodMax(xs) in max(x,y) end

现在我们可以考虑对goodMax([3,4,5]) 的评估是如何进行的:从概念上讲,通过反复替换函数定义的相应分支,它将简化为答案:

  goodMax([3,4,5])
= goodMax(3::[4,5])
= let val y = goodMax([4,5]) in max(3, y) end
= let val y = goodMax(4::[5]) in max(3, y) end
= let val y = (let val y' = goodMax([5]) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = goodMax(5::nil) in max(4, y') end) in max(3, y) end
= let val y = (let val y' = 5 in max(4, y') end) in max(3, y) end
= let val y = max(4, 5) in max(3, y) end
= let val y = (if 4 > 5 then 4 else 5) in max(3, y) end
= let val y = 5 in max(3, y) end
= max(3, 5)
= if 3 > 5 then 3 else 5
= 5

为了清楚起见,我已将内部调用中的 y 重命名为 y'

【讨论】:

  • ` let val y = old_max(tl[3,4,5]) in max(hd[3,4,5], y) end let val y = (let val y' = old_max (tl(tl[3,4,5))) in max(hd(tl[3,4,5],y')) end) in max(hd[3,4,5],y) let val y = (let val y' = old_max([5]) in max(4,y') end) in max(3,y) end let val y = 5 in max (3,y) 5`
猜你喜欢
  • 2020-11-28
  • 2016-01-21
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多