Скажем, у меня есть список вариантов:
let opts = [Some 1; None; Some 4]
Я хотел бы преобразовать их в список, например:
- Если список содержит
None
, результат:None
- В противном случае собираются различные ints.
Относительно просто написать это для этого конкретного случая (используя 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 я использую неявный контекст, требующий наличия некоторого 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;;
Это что-то, что можно сделать с помощью модулей первого класса?
Edit: Хорошо, поэтому мне не приходило в голову попробовать использовать этот код, и он кажется, что он ближе к работе, чем я ожидал! Кажется, что синтаксис действительно действителен, но я получаю этот результат:
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
Первая часть ошибки кажется сбивающей с толку, так как они совпадают, поэтому я предполагаю, что проблема связана со второй. Является ли проблема здесь, что тип возвращаемого значения, по-видимому, не определен? Я полагаю, что это зависит от модуля, который передается - это проблема? Есть ли способ исправить эту реализацию?