2

これが私がこれまでに持っているものです...

fun positive l1 = positive(l1,[],[])
|   positive (l1, p, n) = 
       if hd(l1) < 0
         then positive(tl(l1), p, n @ [hd(l1])
       else if hd(l1) >= 0
         then positive(tl(l1), p @ [hd(l1)], n)
       else if null (h1(l1))
         then p

はい、これは私の教育目的です。私は大学でMLクラスを受講していますが、リスト内の最大の整数を返すプログラムを作成する必要がありました。それ以上のことを行って、そこからポジティブを削除できるかどうかを確認したいと思います。

また、可能であれば、誰かが私にまともなMLの本や入門書を教えてもらえますか?私たちのクラスのテキストは物事をまったく説明していません。

4

2 に答える 2

2

コードが入力されていないことに言及していません。

最初の関数句にはl1、再帰で使用される変数が含まれているだけです。ただし、ここでは、引数として指定されたトリプルの最初の要素として使用されます。これは、SML が使用する Hindley-Milner 型システムと実際には連携していません。これは、おそらく次の非公式の考えでよりよく理解できます。

l1が typeであると仮定することから始めましょう。'aしたがって、関数はその型の引数を取り、不明なものを返す必要があります'a -> ...。ただし、右側で(l1, [], [])は、型を持つ必要がある引数を作成します'a * 'b list * 'c list。しかし、これは引数として関数に渡されるため、'aが と等しいことも意味するはず'a * 'b list * 'c listですが、明らかにそうではありません。

明らかに、これはあなたの当初の意図ではありませんでした。あなたの意図は、リストを引数として取る関数を持ち、同時に2つの追加の累積引数、つまり元のリストの正と負の数のリストを取る再帰ヘルパー関数を持つことだったようです。

これを行うには、少なくともヘルパー関数に別の名前を付けて、その定義が元の関数の定義を再バインドしないようにする必要があります。次に、このヘルパー関数をどのスコープに含めるかについて、いくつかのオプションがあります。一般に、「メイン」関数以外からこのヘルパー関数を呼び出すことに意味がない場合は、 「メイン」関数の外側のスコープ。これは、次のような let バインディングを使用して実行できます。

fun positive xs = 
    let
      fun positive' ys p n = ...
    in
      positive' xs [] [] 
    end

この方法では、ヘルパー関数を関数positives'の外で呼び出すことはできませんpositive

これにより、元のコードにさらにいくつかの問題があることに注意してください。

  • 正の整数のリストのみを返すため、負の整数を追跡する必要はありません。

  • リスト要素を分解するには、パターン マッチングを使用する必要があります。このようにして、リストの先頭と末尾を取得する必要がなくなり、リストに実際に先頭と末尾があるかどうかを確認する必要もなくなります。

    fun foo []      = ... (* input list is empty *)
      | foo (x::xs) = ... (* x is now the head, and xs is the tail *)
    
  • 追加演算子 ( @) は、回避できる場合はいつでも使用しないでください (常に回避できます)。問題は、左側に巨大なリストがあり、右側に小さなリストがある場合、実行時間がひどいことです (これは右側の場合によくあります。単一要素)。したがって、一般に、それを使用することは悪い習慣と見なされるべきです。

    ただし、これには非常に簡単な解決策があります。これは、常にリストの前に要素を連結し (リストを逆の順序で構築)、最後にリストを返すときにリストを逆にする (期待される順序にする) ことです。 ):

    fun foo [] acc = rev acc
      | foo (x::xs) acc = foo xs (x::acc)
    

これらの小さなメモを考えると、最終的には次のような関数になります

fun positive xs =
    let
      fun positive' [] p = rev p
        | positive' (y::ys) p =
          if y < 0 then
            positive' ys p
          else
            positive' ys (y :: p)
    in
      positive' xs []
    end
于 2013-01-18T00:51:51.400 に答える
1

について学びましたList.filterか?ここでは適切かもしれません - type の関数 (述語) と type'a -> boolのリストを取り'a list、述語が に評価される要素のみからなるリストを返しますtrue。例えば:

List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]

intのバージョンを使用して整数と比較しているため、既存のコードは機能しません<。このコードhd(l1) < 0は、 のリストでintはなく、 のリストに対して機能しrealます。数値リテラルは、標準 ML によって自動的に強制されません。を明示的に記述し0.0、テストに使用する必要がありReal.< (hd(l1), 0.0)ます。

標準ライブラリから使用したくない場合はfilter、自分で実装する方法を検討できfilterます。1 つの方法を次に示します。

fun filter f [] = []
  | filter f (h::t) =
      if f h 
      then h :: filter f t 
      else filter f t
于 2013-01-17T22:04:04.217 に答える