オプションのリストがあるとしましょう:
let opts = [Some 1; None; Some 4]
これらを次のようにリストのオプションに変換したいと思います。
- リストに が含まれている場合
None
、結果は次のようになります。None
- それ以外の場合は、さまざまな int が収集されます。
この特定のケースでこれを書くのは比較的簡単です ( CoreとMonad
モジュールを使用):
let sequence foo =
let open Option in
let open Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
ただし、質問のタイトルが示すように、に特化するのではなく、型コンストラクターを抽象化したいと思いますOption
。コアはより高い種類の型の効果を与えるためにファンクターを使用しているようですが、モジュールで抽象化される関数をどのように記述できるかが明確ではありません。Scala では、some の可用性を要求するようにバインドされた暗黙のコンテキストを使用しますMonad[M[_]]
。モジュールを暗黙的に渡す方法がないことを期待していますが、明示的に行うにはどうすればよいですか? 言い換えれば、これに近いものを書くことができますか:
let sequence (module M : Monad.S) foo =
let open M in
let open M.Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
これはファーストクラスモジュールでできることですか?
編集:さて、その特定のコードを実際に使用しようとは思わなかったので、予想よりもうまく機能しているようです! 構文は実際には有効なようですが、次の結果が得られます。
Error: This expression has type 'a M.t but an expression was expected of type 'a M.t
The type constructor M.t would escape its scope
エラーの最初の部分は一致するため、混乱しているように見えるので、問題は2番目にあると推測しています-戻り値の型が決定されていないように見えるという問題はここにありますか? 渡されたモジュールに依存していると思います-これは問題ですか? この実装を修正する方法はありますか?