3

だから私はsmlが初めてで、そのイン/アウトを理解しようとしています。最近、関数 (ブール値を返す) と関数に対して実行する値のリストの 2 つのパラメーターを取るフィルターを作成しようとしました。フィルターが行うことは、関数に対して true を返す値のリストを返すことです。

コード:

fun filter f [] = []  |
   filter f (x::xs) =
      if (f x)
      then x::(filter f xs)
      else (filter f xs);

それでうまくいきます。しかし、私が今やろうとしているのは、真の値と偽のリストを含むタプルを返すことです。私は条件付きで立ち往生しており、別の方法が本当にわかりません。これを解決する方法について何か考えはありますか?

コード:

fun filter2 f [] = ([],[])  |
   filter2 f (x::xs) =
      if (f x)
      then (x::(filter2 f xs), []) (* error *)
      else ([], x::(filter2 f xs)); (* error *)
4

2 に答える 2

2

だから私はそれを行うための良い方法と、それを行うためのより良い方法(IMO)を示します。ただし、「より良い方法」は、次のことを学ぶときの将来の参照用です。

fun filter2 f [] = ([], [])
  | filter2 f (x::xs) = let

  fun ftuple f (x::xs) trueList falseList =  
    if (f x) 
      then ftuple f xs (x::trueList) falseList 
    else ftuple f xs trueList (x::falseList)

    | ftuple _ [] trueList falseList = (trueList, falseList)

in
  ftuple f (x::xs) [] []
end;

あなたが機能しない理由は、あなたが呼び出すx::(filter2 f xs)と、コンパイラはあなたが単一のリストを構築していると単純に想定しているためです。それはタプルであるとは想定していませ。したがって、結果の型がリストのタプルであると自分で考えている間、コンパイラーはトンネルビジョンを取得し、結果の型がリストであると考えます。私の意見では、これがより良いバージョンですfoldr。興味がある場合は関数を調べる必要があります。この手法を使用する方がはるかに優れています。これは、読みやすく、冗長でなく、さらに重要なことに...より予測可能で堅牢であるためです。

fun filter2 f l = foldr (fn(x,xs) => if (f x) then (x::(#1(xs)), #2(xs)) else (#1(xs), x::(#2(xs)))) ([],[]) l;

最初の例が機能する理由は、条件に適合する変数または条件に適合しない変数のコピーを蓄積するデフォルトの空のリストを保存しているためです。ただし、型規則が一致することを確認するように SML コンパイラに明示的に指示する必要があります。戻り値の型がリストのタプルであることを SML が確実に認識できるようにする必要があります。この一連のコマンドに誤りがあると、実行に失敗します。したがって、SML を扱うときは、常に型の推論を検討してください。2 つ目については、ワンライナーであることがわかりますが、Googlefoldrfoldl.

于 2013-04-10T03:33:02.347 に答える