Я новичок в функциональном программировании, поэтому это может быть вопрос из-за неправильного понимания, но я не могу понять это - с точки зрения ООП это кажется таким очевидным...
сценарий: предположим, что у вас есть действующий или микросервисный архитектурный подход, в котором сообщения/запросы отправляются некоторым компонентам, которые их обрабатывают и отвечают. Теперь предположим, что один из компонентов сохраняет некоторые данные из запросов для будущих запросов (например, он вычисляет значение и сохраняет его в кэше, чтобы при следующем поступлении того же запроса вычисления не требовались). Данные могут храниться в памяти.
вопрос: как вы в функциональном программировании вообще, и особенно в f#, справляетесь с таким сценарием? Я предполагаю, что статический словарь не является функциональным подходом, и я не хочу включать какие-либо внешние вещи, такие как хранилища данных, если это возможно.
Или, точнее: Если приложение создает данные, которые будут снова использоваться позже в процессе обработки, где мы храним эти данные?
пример: у вас есть приложение, которое выполняет какие-то задачи с некоторыми исходными данными. Сначала вы сохраняете исходные данные (например, добавляете их в словарь), затем выполняете первую задачу, выполняющую некоторую обработку на основе подмножества данных, затем выполняете вторую задачу, которая добавляет дополнительные данные и так далее, пока все задачи не будут выполнены...
Теперь базовым подходом (насколько я понимаю) будет определение данных и использование задач как своего рода цепочки обработки, которая пересылает обработанные данные, например initial-data -> task-1 -> task-2 -> ... -> done
, но это не соответствует архитектуре, в которой получение/добавление данных выполняется сообщением. базовые и асинхронные.
подход:
Мой первоначальный подход был таким
type Record = { }
let private dummyStore = new System.Collections.Concurrent.ConcurrentBag<Record>()
let search comparison =
let matchingRecords = dummyStore |> Seq.where (comparison)
if matchingRecords |> Seq.isEmpty
then EmptyFailedRequest
else Record (matchingRecords |> Seq.head)
let initialize initialData =
initialData |> Seq.iter (dummyStore.Add)
let add newRecord =
dummyStore.Add(newRecord)
инкапсулированный в модуль, который выглядит как ООП-подход.
После того, как @Gustavo попросил меня привести пример, и, учитывая его предложение, я понял, что могу сделать это так (перейти на один уровень выше к тому месту, где на самом деле вызываются функции):
let handleMessage message store =
// all the operations from above but now with Seq<Record> -> ... -> Seq<Record>
store
let agent = MailboxProcessor.Start(fun inbox->
let rec messageLoop store = async{
let! msg = inbox.Receive()
let modifiedStore = handleMessage msg store
return! messageLoop modifiedStore
}
messageLoop Seq.empty
)
Это хорошо отвечает на вопрос для меня, поскольку он вообще удалил изменчивость и общее состояние. Но когда я просто смотрю на первый подход, я не могу думать ни о каком решении без коллекции вне функций
Обратите внимание, что этот вопрос в f # для объяснения среды, синтаксиса и т. Д. Мне не нужно решение, которое работает, потому что f # является мультипарадигмой, я хотел бы получить для этого функциональный подход.
Я прочитал все вопросы, которые я смог найти на SO до сих пор, но они либо доказывают теоретическую возможность, либо используют коллекции для этого сценария - если они повторяются, пожалуйста, укажите мне правильно направление.