2

list_print : string list -> unitリスト内のすべての文字列を左から右に出力するOcaml関数を記述します。

list_print: string list -> unitそれで、リスト内のすべての文字列を左から書き込みに出力するOcaml関数があるとしましょう。今正しい解決策は次のとおりです。

let list_print lst = List.fold_left (fun ( ) -> fun s -> print_string s) () lst;;

しかし、私のソリューションを書くとき、私はそれをそのように書きました:

let list_print lst = List.fold_left (fun s -> print_string s) () lst;;

しかし、これは私に与えました

エラー:この式にはタイプunitがありますが、タイプ'a->stringの式が必要でした

funの前に最初のパラメータfun()->が必要なのはなぜですか?私はまだOcamlに慣れていないので、この型システムは私をかなり混乱させます

4

2 に答える 2

8

fold_left(および)の目的は、fold_right進行するにつれて値を累積することです。追加のパラメーターは、この累積値です。

あなたの問題に使用できList.iterます。値が蓄積されません。

type の値を累積List.iterする のバージョンと考えることができます。実際、次のように実装できます。List.fold_leftunit

let iter f = List.fold_left (fun () a -> f a) ()

ポイントは (いつものようにunit) 型の値が 1 つしかないということです。そのため、値が重要でない場合を表します。

于 2012-10-09T02:16:40.567 に答える
1

を使用したいList.fold_leftのですが、それは問題ありませんが、その関数のドキュメントを読むことから始める必要があります。公式ドキュメントは非常に短いです:

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.

まず、その関数のタイプです。タイプは

 ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

つまり、関数fold_leftには3つの引数と1つの結果値があります。最初の引数の型は('a -> 'b -> 'a)です。2番目の引数の型は'aです。3番目の引数の型は'b listです。関数の結果値のタイプは'a。です。

さて、あなたの場合、あなたは文字列を印刷したいと思います。したがって、実際には結果値は必要ありません。副作用が必要です。ただし、OCamlでは、すべての関数に結果値が必要です。()したがって、タイプが。の空の値を使用しますunit。したがって、typeパラメータ'aはあなたの場合と等しくなりunitます。

typeパラメータ'bstring、文字列のリストで作業する必要があるためです。

したがって、あなたの場合、関数fold_leftはタイプを持っている必要があります

 (unit -> string -> unit) -> unit -> string list -> unit.     

の最初の引数はfold_left、タイプがである必要がありunit->string->unitます。つまり、2つの引数を持つ関数である必要があります。最初の引数は空の値、つまり()2番目の引数は文字列です。したがって、の最初の引数fold_leftはこの種の関数でなければなりません。

 fun x y -> ...

ここで、タイプとタイプであるx必要があります。は常にに等しくなるため、この引数を変数として記述する必要はありません。代わりに、単純に、またはダミーの引数を記述することもできます。(構文はと同じ機能を提供します。)unitystringx()x()_fun x -> fun y -> ...fun x y -> ...

これで、fold_leftがどのように機能するかを理解し始めることができます。これは明らかに宿題の質問なので、このタスクはあなたに任せます。

于 2012-10-10T08:07:30.680 に答える