Я пытаюсь понять и / или найти примеры того, как надежные приложения OCaml работают со средой конфигурации. Я приехал из мира Haskell, где я бы использовал монаду Reader
для решения этой проблемы. В частности, я хочу определить конфигурацию верхнего уровня, которую я могу передать по всему моему приложению, но только некоторые функции в моем приложении должны будут использовать конфигурацию.
Чтобы мотивировать это, рассмотрите простой исполняемый файл который запрашивает базу данных. Я хотел бы определить главный файл верхнего уровня, который может выполнять такие действия, как настройка пула соединений или создание регистратора, который будет использоваться во всем приложении.
Я предполагаю, что OCaml имеет некоторый шаблон для работы с это, но я не могу найти хороших примеров. Я бы предпочел не определять свою Reader
монаду и функторизовать все приложение, если мне это не нужно.
При этом, это тоже уродливо
main.mli
module Config : sig
type t = {
fooConfig : Foo.Config.t;
dbClientConfig : DB_client.Config.t;
}
val make : Foo.Config.t -> DB_client.Config.t -> t
end
val main : Config.t -> unit
foo.mli
module Config : sig
type t = {
dbConfig : DB_client.Config.t;
}
end
(** fooFunc will need to pass the dbConfig, but it does not actually explicitly need anything in the config **)
val fooFunc : Config.t -> string -> unit
db_client.mli
module Config : sig
type t = {
connPool : SomeConnPool
}
end
(** Finally, I need to use the config to grab a connection out of the pool **)
val writeToDb : Config.t -> string -> (string, string) Lwt.result
Я не хочу, чтобы явные аргументы функции «выше в стеке выполнения» явно зависели от конфигурации, которую они никогда не будут использовать.
Есть ли хороший функциональный шаблон для работы с этим вложенным связывание зависимостей? Я был бы признателен за любые примеры кода, на которые кто-то может указать, чтобы я мог изучить лучший подход.