1

この関数はリストの最大数を見つけますが、それを理解するのが難しいです:

fun max1 (xs : int list) = 
if null xs
    then NONE
        else 
            let val tl_ans =  max1(tl xs)
        in 
            if isSome tl_ans andalso valOf tl_ans > hd xs
                then 
                    tl_ans
                else 
                    SOME (hd xs)
end;

まだ設定されていないため、インラインでどのようtl_ansに計算されていますか?if isSome tl_ans andalso valOf tl_ans > hd xs

4

3 に答える 3

2

これは、標準 ML でそのような関数を記述する最も慣用的な方法ではありません。別の方法で書くと、それがどのように機能するかをよりよく理解できると思います。関数valOfhdおよび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
于 2013-09-13T13:29:40.740 に答える
2

台詞

let val tl_ans =  max1(tl xs)
in 
    if isSome tl_ans andalso valOf tl_ans > hd xs    

letを次のコードtl_ans入れることを意味します。 (通常、 の値は名前 (または変数) "tl_ans" にバインドされていると言います。)max1 (tl xs)
max1 (tl xs)

と全く同じ意味です

if isSome (max1 (tl xs)) andalso valOf (max1 (tl xs)) > hd xs

ただし、値max1 (tl xs)は 1 回だけ計算されます。

于 2013-09-13T06:39:46.017 に答える