12

文字列のリストを受け取り、リスト内の最大の文字列を見つける関数を作成する必要があります。問題は、List.foldl を使用してリストを反復処理する必要があり、List,foldl のライブラリ関数以外の再帰呼び出しを使用できないことです。

私が書いた

fun longest_string1(xs)= 
case xs of 
[] => ""  
| x::xs' => List.foldl((fn (s,x) => if String.size s > String.size x then s else x) "" x,)

私の解釈は次 のとおりです

。リストの先頭項目に対するアキュムレータを表します。-初期アキュムレータを空の文字列に設定し、初期比較値を高次関数によって渡された初期リストの先頭に設定します





ただし、型チェックは行いません。

私の問題は、 List.foldl 関数自体と、そのパラメーターを正確に読み取る方法を理解することにあると思います。誰か説明をお願いできますか?

4

1 に答える 1

36

したがって、投稿したコードの場合:

  1. 空のリストのケースは必要ありません。foldl がそれを処理します。x の代わりに xs を foldl に渡すだけです。
  2. foldl はカリー化されているため、パラメーターを括弧で囲むべきではありません。

それ以外は、実際には正しいように見えます。とにかく、foldl がどのように機能するのかまだよくわからない場合は、ここに非常に長く完全な説明があります ;)

さて、List.foldl から始めましょう。

val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b

したがって、3 つのパラメータがあります。1 つは後で考える関数で、2 番目は戻り値の型と同じ型の値で、最後はリストです。

それでは、簡単な例を見てみましょう。たとえば、int のリストがあり、すべての数値を合計したいとします。これを行うことができます:

fun sum [] = 0
  | sum (x::xs) = x + sum xs

または、foldl を使用することもできます (私は怠け者なので、List.foldl の代わりに foldl と書きます)。

したがって、リストが 3 番目のパラメーターであることがわかります。2 番目は、リストが空の場合に意味のある開始値またはアキュムレータのようなものである必要があります。合計の場合、それは 0 になります。

最初のパラメーターは関数で、ここが難しい部分です。タイプは次のとおりです。

fn : 'a * 'b -> 'b

'a はリスト内の要素の型でもあるので、これがリストの項目である場合は意味があります。'b は開始値戻り値の型です。

実際には、foldl はリストの最初の要素とアキュムレータを使用して関数を呼び出します。次に、新しいアキュムレータとしての結果とリストの残りを使用して自分自身を呼び出します。したがって、これを行うと:

foldl foo 0 [1,2,3]

やります

foo (1,0)

その後

foldl foo (foo (1,0)) [2,3]

等々。

したがって、リストを合計するために、次の関数を作成します。

fn (x,acc) => x + acc

したがって、これを行うことができます:

fun sum xs = foldl (fn (x,acc) => x + acc) 0 xs

または、さらに単純な

val sum = foldl op+ 0

(op+前に使用した無名関数と同じことを行います)

リストを見てみましょう[1,2,3]

foldl op+ 0 [1,2,3]
foldl op+ (op+ (1,0)) [2,3] -> foldl op+ 1 [2,3]
foldl op+ (op+ (2,1)) [3]   -> foldl op+ 3 [3]
foldl op+ (op+ (3,3)) []    -> foldl op+ 6 []
6
于 2013-02-06T23:08:57.147 に答える