2

Ocaml でのパターン マッチングに関して少し問題があります。

基本的に、リストを受け取り、それが逆順かどうかをチェックする reversed という名前の関数を作成する必要があります。

ここのところ:

let rec reversed (x:int list):bool =
   match x with
   | [] -> true
   | y::z::tl -> if y < z then false else reversed tl;
   | y::[] -> true;;

できます!(実際には驚いたことに:P)しかし、私が見ることができる欠陥があります。つまり、tlがこれ以上ない場合、一致しません。これをテストすると、true が返されます。

  reversed [5;4;3;1;2];;

テールがなくなり、単純に y::[] に一致するため、これは完全に理解できます。

どうすればこれを修正できますか?

PS: 今日は Ocaml との最初の日です。質問が非常に簡単な場合は申し訳ありません:D

PPS: 意図的に Core のみを使用しています。(モジュールなし)

PPPS: 私が根本的に間違ったことをしている場合は理解しています。それを指摘してください。

4

4 に答える 4

4

関数の問題は次のとおりです。

| y::z::tl -> if y < z then false else reversed tl;

リストを見てみましょう: [5;4;3;1;2]

このように分解されます:

| 5::4::[3;1;2]

そして、5 と 4 を比較し、[3;2;1] で元に戻します。これは、4 と 3の比較が行われていないことを意味します。([5;4;99;98;97] のようなリストで試すことができます。予期しない結果が得られます)。

あなたがすべきことは、z でテストしてから、残りのリストで reverted を呼び出すことです。しかし、次のようなものを試してみると:

| y::z::_ -> if y < z then false else reversed z;

z は int (もはや int リストではない) であるため、コンパイラはあなたに怒鳴りつけます。これを解決するには、 tl の前に z を追加してリストを「再構築」します。

| y::z::tl -> if y < z then false else reversed (z::tl)

または、 z を抽出しながら、リストに y (z を含む) の後に名前を付けます。

| y::(z::_ as tl) -> if y < z then false else reversed tl

問題についてのあなたの推測については、私はあなたの論理を理解していますが、実際にはそのようには機能しません。[] は、通常のノードであるかのように、分解で「名前を付ける」ことができます。

リストの最後に到達したかどうかをテストする (悪い) 関数の例を見てください。

let is_end l = match l with | a -> false | [] -> true;;

それをインタープリターに入れようとすると、次のメッセージが表示されます。 Warning 11: this match case is unused.

これは、 [] が最初の一致ケースで既にキャッチされているためです。で試すことができますがis_end []、false が返されます。

これを処理する正しい方法は、コードで行った方法です。

let is_end l = match l with | x::_ -> false | [] -> true;;

于 2013-08-02T12:43:23.457 に答える
2

プログラムのロジックが間違っています。リストが逆になっている (減少している?) かどうかを確認したい。しかし、あなたのプログラムは入力時に失敗します

[5;3;4;2;1]

反転/減少していることを伝えます。これは、3 をドロップするのが早すぎるためです。中間節は次のようになります。

   | y::z::tl -> if y < z then false else reversed (z::tl);
于 2013-08-02T12:40:48.380 に答える
1

を使用する必要があります| y::z::tl -> if y < z then false else reversed (z::tl)

y > z の場合、z はまだ次の項目と比較されていないため、リストの次のラウンドから z を削除しないでください。

また、必要ありません; その行で。

正しいコードは

let rec reversed = function
  | [] -> true
  | hd::[] -> true
  | hd1::hd2::tl ->
    if hd1 < hd2 then false
    else reversed (hd2::tl)
于 2013-08-03T13:07:07.220 に答える