Я застрял в рефакторинге большой структуры данных в Elm. Я знаю, как бы реализовать это на ОО-языках, но у меня нет опыта работы с ними. Я не могу точно выразить, в чем заключается моя проблема, потому что я могу сформулировать ее только в терминах ООП, которые не применяются. Итак, я приведу пример, который является упрощенной версией модуля, который я реорганизую.
Предположим, у меня есть этот тип:
type alias Book = { title : String, text : String }
, и у меня есть две книги:
englishBook = { title = "An English Book", text = "This book is an Eglish book." }
frenchBook = { title = "Un livre Francais", text = "Ce livre est un livre Francais." }
Есть связанная index
функция для вычисления того, какие слова входят в Book
:
index = String.words >> Set.fromList
Вот уже моя первая проблема. Когда index
принимает строку, пользователь модуля должен знать, как взять текст из книги. Вместо этого мои привычки говорят, что функция должна сделать это для нас. Так что index
может вести себя как метод и принимать Book
в качестве первого аргумента: index = .text >> String.words >> Set.fromList
. Но это также кажется странным.
Это еще не конец, потому что генератор индекса должен быть параметризуемым. В зависимости от книги, она должна делать разные вещи. Таким образом, я мог бы добавить функцию индекса следующим образом:
englishBook = { title = "...", text = "...", index = englishIndex }
frenchBook = { title = "...", text = "...", index = frenchIndex }
теперь у каждой книги есть функция для построения своего индекса. Но все же вызывающий абонент должен предоставить запись, когда ему нужен индекс:
wordsInEnglishBook = englishBook.index englishBook.text
, что не является хорошим решением для меня, поскольку он обременяет вызывающего абонента внутренними компонентами модуля. А что если эта часть инкапсулирована конструктором?
book title text index = { title = title, text = text, index = \_ -> index text }
Теперь я прошел полный круг и реализовал метод. Так каково идиоматическое решение для этого вяза ?