これは、標準 ML でそのような関数を記述する最も慣用的な方法ではありません。別の方法で書くと、それがどのように機能するかをよりよく理解できると思います。関数valOf、hdおよびtlはいわゆる部分関数NONEであり、それらを使用する唯一の言い訳は、入力がそれぞれまたはでないことを保証する[]場合です (この場合、プログラムは例外を呼び出します)。
valOf, hdorを使用すると、リストが空 (例: ) であるか、オプションが存在するか(例: )tailを確認する必要があるため、使用の利便性は制限されます。代わりに、パターン マッチング (またはこれらの関数のより堅牢なバージョン) を使用することが望まれます。null xsisSome ans
以下に、同じ関数を別の 2 つの方法で記述しました。
(* 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