这不是在标准 ML 中编写此类函数的最惯用方式。我建议以另一种方式编写它,可以更好地理解它是如何工作的。函数valOf
,hd
和tl
是所谓的部分函数,使用它们的唯一借口是确保它们的输入不是NONE
或[]
分别(在这种情况下程序将调用异常)。
使用valOf
, hd
ortail
将因此要求您检查列表是否为空(例如null xs
)或选项是否存在(例如isSome ans
),因此使用它的便利性受到限制。相反,需要使用模式匹配(或更强大的这些功能版本)。
下面我以另外两种方式编写了相同的函数,其中一种类似于您提供的那种。
(* For a list with at least one element in it, check to see if there is a
* greatest element in the tail (xs). If there isn't, then x is the greatest
* element. Otherwise, whichever is the greatest of x and y is the greatest.
*
* This solution is comparable to the one you have above: Find a solution
* for the "smaller" problem (i.e. the reduced list in which x isn't in),
* and then combine the solution. This means making a recursive call to a
* function that doesn't exist at the time of writing it. *)
fun max [] = NONE
| max (x::xs) =
(case max xs of
NONE => SOME x
| SOME y => SOME (Int.max (x, y)))
(* If we were to use a let-expression instead of a case-of, but still restrict
* ourselves from using partial functions, we might make a helper function: *)
fun maxOpt (x, NONE) = SOME x
| maxOpt (x, SOME y) = SOME (Int.max (x, y))
(* Now the essence of the let-expression is boiled down: It finds the largest
* value in the tail, xs, and if it exists, finds the largest of that and x,
* and pass it as a result packed in SOME. *)
fun max [] = NONE
| max (x::xs) =
let val y_opt = max xs
in maxOpt (x, y_opt) end
(* In fact, one can store the largest value so far in the front of the list.
* This is only because the return type is int option, and the input type is
* int list. If the return type were dramatically different, it might not be
* so easy. *)
fun max [] = NONE
| max (x::y::xs) = max (Int.max (x,y)::xs)
| max [x] = SOME x