List 从SML中的列表中获取最大值

List 从SML中的列表中获取最大值,list,recursion,sml,List,Recursion,Sml,我目前正在学习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

我目前正在学习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
hdxs的类型是int和tl_ans,我认为是list类型。 为什么这个代码可以工作?系统如何评估递归?
如果您可以使用xs=[3,4,5]向我展示这是如何工作的,那就太好了

首先让我将此代码重写为一个等效但更可读的版本:

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
现在我们可以考虑如何评价GooMax [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。

首先让我将此代码重写为一个等效但更可读的版本:

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
现在我们可以考虑如何评价GooMax [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。

'maxhd[3,4,5]中的let val y=old_maxtl[3,4,5],y end let val y=let val y'=old_maxtl[3,4,5],maxhd[3,4,5]中的y'end,y let val y=let val y'=old_max[5]在max4中,y’end在max3中,y end让val y=5在max3中,y5’`让val y=old_maxtl[3,4,5]在maxhd[3,4,5]中,y end让val y=let val y'=old_maxtl[3,4,5],y’end在maxhd[3,4,5]中,y让val y=let val y'=old_max[5]在max4中,y’end在max3中,y end让val y=5在max3中,y5’`让val y=old_maxtl[3,4,5]在maxhd[3,4,5]中,y end让val y=let val y'=old_maxtl[3,4,5],y’end在maxhd[3,4,5]中,y让val y=let val y'=old_max[5]在max4中,y’end在max3中,y end让val y=5在max3中,y 5‘好的。我在试图将代码放入注释框时遇到了麻烦。谢谢Andreas!我能够理解您的代码是如何工作的,并将其应用到我的代码中。使用帮助函数使代码更加优雅:我在假设中犯了错误,因为我没有替换所有的branches在我评估函数之前。递归确实是一个具有挑战性的主题。FWIW,max函数已经作为Int.max存在于标准库中。另外,第三种情况的右侧可以明显简化为maxx,goodMax xs-我这样做不是为了演示let中的缩减是如何工作的。最后,我建议使用ra在空的情况下会引发异常,因为结果0并不完全正确。总之,您可以使用fold将函数表示为简单的fun goodMax[]=raise empty | goodMaxx::xs=List.foldl Int.max x xs.`let val y=old_maxtl[3,4,5],y end let val y=let val y'=old_maxtl[3,4,5 in maxhdtl[3,4,5],y'end in maxhd[3,4,5],y let val y=let val y'=old_max[5]在max4中,y’end在max3中,y end让val y=5在max3中,y 5‘好的。我在试图将代码放入注释框时遇到了麻烦。谢谢Andreas!我能够理解您的代码是如何工作的,并将其应用到我的代码中。使用帮助函数使代码更加优雅:我在假设中犯了错误,因为我没有替换所有的branches在我评估函数之前。递归确实是一个具有挑战性的主题。FWIW,max函数已经作为Int.max存在于标准库中。另外,第三种情况的右侧可以明显简化为maxx,goodMax xs-我这样做不是为了演示let中的缩减是如何工作的。最后,我建议使用ra在空的情况下会引发异常,因为结果0并不完全正确。总之,您可以使用fold将函数表示为简单的fun goodMax[]=raise empty | goodMaxx::xs=List.foldl Int.max x xs。